00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "tinyGraphicsStateGuardian.h"
00016 #include "tinyGeomMunger.h"
00017 #include "tinyTextureContext.h"
00018 #include "config_tinydisplay.h"
00019 #include "pStatTimer.h"
00020 #include "geomVertexReader.h"
00021 #include "ambientLight.h"
00022 #include "pointLight.h"
00023 #include "directionalLight.h"
00024 #include "spotlight.h"
00025 #include "depthWriteAttrib.h"
00026 #include "depthOffsetAttrib.h"
00027 #include "colorWriteAttrib.h"
00028 #include "alphaTestAttrib.h"
00029 #include "depthTestAttrib.h"
00030 #include "shadeModelAttrib.h"
00031 #include "cullFaceAttrib.h"
00032 #include "rescaleNormalAttrib.h"
00033 #include "materialAttrib.h"
00034 #include "lightAttrib.h"
00035 #include "scissorAttrib.h"
00036 #include "bitMask.h"
00037 #include "zgl.h"
00038 #include "zmath.h"
00039 #include "ztriangle_table.h"
00040 #include "store_pixel_table.h"
00041 #include "graphicsEngine.h"
00042
00043 TypeHandle TinyGraphicsStateGuardian::_type_handle;
00044
00045 PStatCollector TinyGraphicsStateGuardian::_vertices_immediate_pcollector("Vertices:Immediate mode");
00046 PStatCollector TinyGraphicsStateGuardian::_draw_transform_pcollector("Draw:Transform");
00047 PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_untextured_pcollector("Pixels:White untextured");
00048 PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_untextured_pcollector("Pixels:Flat untextured");
00049 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_untextured_pcollector("Pixels:Smooth untextured");
00050 PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_textured_pcollector("Pixels:White textured");
00051 PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_textured_pcollector("Pixels:Flat textured");
00052 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_textured_pcollector("Pixels:Smooth textured");
00053 PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_perspective_pcollector("Pixels:White perspective");
00054 PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_perspective_pcollector("Pixels:Flat perspective");
00055 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_perspective_pcollector("Pixels:Smooth perspective");
00056 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_multitex2_pcollector("Pixels:Smooth multitex 2");
00057 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_multitex3_pcollector("Pixels:Smooth multitex 3");
00058
00059
00060
00061
00062
00063
00064 TinyGraphicsStateGuardian::
00065 TinyGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
00066 TinyGraphicsStateGuardian *share_with) :
00067 GraphicsStateGuardian(CS_yup_right, engine, pipe)
00068 {
00069 _current_frame_buffer = NULL;
00070 _aux_frame_buffer = NULL;
00071 _c = NULL;
00072 _vertices = NULL;
00073 _vertices_size = 0;
00074 }
00075
00076
00077
00078
00079
00080
00081 TinyGraphicsStateGuardian::
00082 ~TinyGraphicsStateGuardian() {
00083 }
00084
00085
00086
00087
00088
00089
00090
00091 void TinyGraphicsStateGuardian::
00092 reset() {
00093 free_pointers();
00094 GraphicsStateGuardian::reset();
00095
00096
00097
00098 _inv_state_mask.clear_bit(ColorAttrib::get_class_slot());
00099 _inv_state_mask.clear_bit(ColorScaleAttrib::get_class_slot());
00100 _inv_state_mask.clear_bit(CullFaceAttrib::get_class_slot());
00101 _inv_state_mask.clear_bit(DepthOffsetAttrib::get_class_slot());
00102 _inv_state_mask.clear_bit(RenderModeAttrib::get_class_slot());
00103 _inv_state_mask.clear_bit(RescaleNormalAttrib::get_class_slot());
00104 _inv_state_mask.clear_bit(TextureAttrib::get_class_slot());
00105 _inv_state_mask.clear_bit(MaterialAttrib::get_class_slot());
00106 _inv_state_mask.clear_bit(LightAttrib::get_class_slot());
00107 _inv_state_mask.clear_bit(ScissorAttrib::get_class_slot());
00108
00109 if (_c != (GLContext *)NULL) {
00110 glClose(_c);
00111 _c = NULL;
00112 }
00113
00114 _c = (GLContext *)gl_zalloc(sizeof(GLContext));
00115 glInit(_c, _current_frame_buffer);
00116
00117 _c->draw_triangle_front = gl_draw_triangle_fill;
00118 _c->draw_triangle_back = gl_draw_triangle_fill;
00119
00120 _supported_geom_rendering =
00121 Geom::GR_point |
00122 Geom::GR_indexed_other |
00123 Geom::GR_triangle_strip |
00124 Geom::GR_flat_last_vertex;
00125
00126 _max_texture_dimension = (1 << ZB_POINT_ST_FRAC_BITS);
00127 _max_texture_stages = MAX_TEXTURE_STAGES;
00128 _max_lights = MAX_LIGHTS;
00129
00130 _color_scale_via_lighting = false;
00131 _alpha_scale_via_texture = false;
00132 _runtime_color_scale = true;
00133
00134 _color_material_flags = 0;
00135 _texturing_state = 0;
00136 _texfilter_state = 0;
00137 _texture_replace = false;
00138 _filled_flat = false;
00139 _auto_rescale_normal = false;
00140
00141
00142
00143 add_gsg(this);
00144 }
00145
00146
00147
00148
00149
00150
00151
00152 void TinyGraphicsStateGuardian::
00153 free_pointers() {
00154 if (_aux_frame_buffer != (ZBuffer *)NULL) {
00155 ZB_close(_aux_frame_buffer);
00156 _aux_frame_buffer = NULL;
00157 }
00158
00159 if (_vertices != (GLVertex *)NULL) {
00160 PANDA_FREE_ARRAY(_vertices);
00161 _vertices = NULL;
00162 }
00163 _vertices_size = 0;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 void TinyGraphicsStateGuardian::
00175 close_gsg() {
00176 GraphicsStateGuardian::close_gsg();
00177
00178 if (_c != (GLContext *)NULL) {
00179 glClose(_c);
00180 _c = NULL;
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 bool TinyGraphicsStateGuardian::
00193 depth_offset_decals() {
00194 return false;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 PT(GeomMunger) TinyGraphicsStateGuardian::
00204 make_geom_munger(const RenderState *state, Thread *current_thread) {
00205 PT(TinyGeomMunger) munger = new TinyGeomMunger(this, state);
00206 return GeomMunger::register_munger(munger, current_thread);
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 void TinyGraphicsStateGuardian::
00221 clear(DrawableRegion *clearable) {
00222 PStatTimer timer(_clear_pcollector);
00223
00224 if ((!clearable->get_clear_color_active())&&
00225 (!clearable->get_clear_depth_active())&&
00226 (!clearable->get_clear_stencil_active())) {
00227 return;
00228 }
00229
00230 set_state_and_transform(RenderState::make_empty(), _internal_transform);
00231
00232 bool clear_color = false;
00233 int r, g, b, a;
00234 if (clearable->get_clear_color_active()) {
00235 LColor v = clearable->get_clear_color();
00236 r = (int)(v[0] * 0xffff);
00237 g = (int)(v[1] * 0xffff);
00238 b = (int)(v[2] * 0xffff);
00239 a = (int)(v[3] * 0xffff);
00240 clear_color = true;
00241 }
00242
00243 bool clear_z = false;
00244 int z;
00245 if (clearable->get_clear_depth_active()) {
00246
00247
00248 z = 0;
00249 clear_z = true;
00250 }
00251
00252 ZB_clear_viewport(_c->zb, clear_z, z,
00253 clear_color, r, g, b, a,
00254 _c->viewport.xmin, _c->viewport.ymin,
00255 _c->viewport.xsize, _c->viewport.ysize);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264 void TinyGraphicsStateGuardian::
00265 prepare_display_region(DisplayRegionPipelineReader *dr) {
00266 nassertv(dr != (DisplayRegionPipelineReader *)NULL);
00267 GraphicsStateGuardian::prepare_display_region(dr);
00268
00269 int xmin, ymin, xsize, ysize;
00270 dr->get_region_pixels_i(xmin, ymin, xsize, ysize);
00271
00272 PN_stdfloat pixel_factor = _current_display_region->get_pixel_factor();
00273 if (pixel_factor != 1.0) {
00274
00275
00276 xmin = 0;
00277 ymin = 0;
00278 xsize = int(xsize * pixel_factor);
00279 ysize = int(ysize * pixel_factor);
00280 if (_aux_frame_buffer == (ZBuffer *)NULL) {
00281 _aux_frame_buffer = ZB_open(xsize, ysize, ZB_MODE_RGBA, 0, 0, 0, 0);
00282 } else if (_aux_frame_buffer->xsize < xsize || _aux_frame_buffer->ysize < ysize) {
00283 ZB_resize(_aux_frame_buffer, NULL,
00284 max(_aux_frame_buffer->xsize, xsize),
00285 max(_aux_frame_buffer->ysize, ysize));
00286 }
00287 _c->zb = _aux_frame_buffer;
00288
00289 } else {
00290
00291 _c->zb = _current_frame_buffer;
00292 }
00293
00294 _c->viewport.xmin = xmin;
00295 _c->viewport.ymin = ymin;
00296 _c->viewport.xsize = xsize;
00297 _c->viewport.ysize = ysize;
00298 set_scissor(0.0f, 1.0f, 0.0f, 1.0f);
00299
00300 nassertv(xmin >= 0 && xmin < _c->zb->xsize &&
00301 ymin >= 0 && ymin < _c->zb->ysize &&
00302 xmin + xsize >= 0 && xmin + xsize <= _c->zb->xsize &&
00303 ymin + ysize >= 0 && ymin + ysize <= _c->zb->ysize);
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 CPT(TransformState) TinyGraphicsStateGuardian::
00318 calc_projection_mat(const Lens *lens) {
00319 if (lens == (Lens *)NULL) {
00320 return NULL;
00321 }
00322
00323 if (!lens->is_linear()) {
00324 return NULL;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 LMatrix4 result =
00336 LMatrix4::convert_mat(CS_yup_right, _current_lens->get_coordinate_system()) *
00337 lens->get_projection_mat(_current_stereo_channel);
00338
00339 if (_scene_setup->get_inverted()) {
00340
00341
00342 result *= LMatrix4::scale_mat(1.0f, -1.0f, 1.0f);
00343 }
00344
00345 return TransformState::make_mat(result);
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 bool TinyGraphicsStateGuardian::
00361 prepare_lens() {
00362 _transform_stale = true;
00363 return true;
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 bool TinyGraphicsStateGuardian::
00380 begin_frame(Thread *current_thread) {
00381 if (!GraphicsStateGuardian::begin_frame(current_thread)) {
00382 return false;
00383 }
00384
00385 _c->zb = _current_frame_buffer;
00386
00387 #ifdef DO_PSTATS
00388 _vertices_immediate_pcollector.clear_level();
00389
00390 _pixel_count_white_untextured_pcollector.clear_level();
00391 _pixel_count_flat_untextured_pcollector.clear_level();
00392 _pixel_count_smooth_untextured_pcollector.clear_level();
00393 _pixel_count_white_textured_pcollector.clear_level();
00394 _pixel_count_flat_textured_pcollector.clear_level();
00395 _pixel_count_smooth_textured_pcollector.clear_level();
00396 _pixel_count_white_perspective_pcollector.clear_level();
00397 _pixel_count_flat_perspective_pcollector.clear_level();
00398 _pixel_count_smooth_perspective_pcollector.clear_level();
00399 _pixel_count_smooth_multitex2_pcollector.clear_level();
00400 _pixel_count_smooth_multitex3_pcollector.clear_level();
00401 #endif
00402
00403 return true;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 bool TinyGraphicsStateGuardian::
00422 begin_scene() {
00423 return GraphicsStateGuardian::begin_scene();
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 void TinyGraphicsStateGuardian::
00436 end_scene() {
00437 if (_c->zb == _aux_frame_buffer) {
00438
00439
00440 int xmin, ymin, xsize, ysize;
00441 _current_display_region->get_region_pixels_i(xmin, ymin, xsize, ysize);
00442 PN_stdfloat pixel_factor = _current_display_region->get_pixel_factor();
00443
00444 int fb_xsize = int(xsize * pixel_factor);
00445 int fb_ysize = int(ysize * pixel_factor);
00446
00447 ZB_zoomFrameBuffer(_current_frame_buffer, xmin, ymin, xsize, ysize,
00448 _aux_frame_buffer, 0, 0, fb_xsize, fb_ysize);
00449 _c->zb = _current_frame_buffer;
00450 }
00451
00452
00453 clear_light_state();
00454 _plights.clear();
00455 _dlights.clear();
00456 _slights.clear();
00457
00458 GraphicsStateGuardian::end_scene();
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468 void TinyGraphicsStateGuardian::
00469 end_frame(Thread *current_thread) {
00470 GraphicsStateGuardian::end_frame(current_thread);
00471
00472 #ifndef NDEBUG
00473 static ConfigVariableBool td_show_zbuffer
00474 ("td-show-zbuffer", false,
00475 PRC_DESC("Set this true to draw the ZBuffer instead of the visible buffer, when rendering with tinydisplay. This is useful to aid debugging the ZBuffer"));
00476 if (td_show_zbuffer) {
00477 PIXEL *tp = _current_frame_buffer->pbuf;
00478 ZPOINT *tz = _current_frame_buffer->zbuf;
00479 for (int yi = 0; yi < _current_frame_buffer->ysize; ++yi) {
00480 for (int xi = 0; xi < _current_frame_buffer->xsize; ++xi) {
00481 (*tp) = (int)(*tz);
00482 ++tz;
00483 ++tp;
00484 }
00485 }
00486 }
00487 #endif // NDEBUG
00488
00489 #ifdef DO_PSTATS
00490
00491 _vertices_immediate_pcollector.flush_level();
00492
00493 _pixel_count_white_untextured_pcollector.flush_level();
00494 _pixel_count_flat_untextured_pcollector.flush_level();
00495 _pixel_count_smooth_untextured_pcollector.flush_level();
00496 _pixel_count_white_textured_pcollector.flush_level();
00497 _pixel_count_flat_textured_pcollector.flush_level();
00498 _pixel_count_smooth_textured_pcollector.flush_level();
00499 _pixel_count_white_perspective_pcollector.flush_level();
00500 _pixel_count_flat_perspective_pcollector.flush_level();
00501 _pixel_count_smooth_perspective_pcollector.flush_level();
00502 _pixel_count_smooth_multitex2_pcollector.flush_level();
00503 _pixel_count_smooth_multitex3_pcollector.flush_level();
00504 #endif // DO_PSTATS
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 bool TinyGraphicsStateGuardian::
00517 begin_draw_primitives(const GeomPipelineReader *geom_reader,
00518 const GeomMunger *munger,
00519 const GeomVertexDataPipelineReader *data_reader,
00520 bool force) {
00521 #ifndef NDEBUG
00522 if (tinydisplay_cat.is_spam()) {
00523 tinydisplay_cat.spam() << "begin_draw_primitives: " << *(data_reader->get_object()) << "\n";
00524 }
00525 #endif // NDEBUG
00526
00527 if (!GraphicsStateGuardian::begin_draw_primitives(geom_reader, munger, data_reader, force)) {
00528 return false;
00529 }
00530 nassertr(_data_reader != (GeomVertexDataPipelineReader *)NULL, false);
00531
00532 PStatTimer timer(_draw_transform_pcollector);
00533
00534
00535 if (_data_reader->is_vertex_transformed()) {
00536
00537
00538
00539 const TransformState *ident = TransformState::make_identity();
00540 load_matrix(&_c->matrix_model_view, ident);
00541 load_matrix(&_c->matrix_projection, _scissor_mat);
00542 load_matrix(&_c->matrix_model_view_inv, ident);
00543 load_matrix(&_c->matrix_model_projection, _scissor_mat);
00544 _c->matrix_model_projection_no_w_transform = 1;
00545 _transform_stale = true;
00546
00547 } else if (_transform_stale) {
00548
00549
00550 CPT(TransformState) scissor_proj_mat = _scissor_mat->compose(_projection_mat);
00551
00552 if (_c->lighting_enabled) {
00553
00554
00555
00556 load_matrix(&_c->matrix_model_view, _internal_transform);
00557 load_matrix(&_c->matrix_projection, scissor_proj_mat);
00558
00559
00560 M4 tmp;
00561 gl_M4_Inv(&tmp, &_c->matrix_model_view);
00562 gl_M4_Transpose(&_c->matrix_model_view_inv, &tmp);
00563
00564 }
00565
00566
00567 load_matrix(&_c->matrix_model_projection,
00568 scissor_proj_mat->compose(_internal_transform));
00569
00570
00571 _c->matrix_model_projection_no_w_transform = 0;
00572 PN_stdfloat *m = &_c->matrix_model_projection.m[0][0];
00573 if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) {
00574 _c->matrix_model_projection_no_w_transform = 1;
00575 }
00576 _transform_stale = false;
00577 }
00578
00579
00580
00581 int num_vertices = data_reader->get_num_rows();
00582 _min_vertex = num_vertices;
00583 _max_vertex = 0;
00584 int num_prims = geom_reader->get_num_primitives();
00585 int i;
00586 for (i = 0; i < num_prims; ++i) {
00587 CPT(GeomPrimitive) prim = geom_reader->get_primitive(i);
00588 int nv = prim->get_min_vertex();
00589 _min_vertex = min(_min_vertex, nv);
00590 int xv = prim->get_max_vertex();
00591 _max_vertex = max(_max_vertex, xv);
00592 }
00593 if (_min_vertex > _max_vertex) {
00594 return false;
00595 }
00596
00597
00598
00599 int num_used_vertices = _max_vertex - _min_vertex + 1;
00600 if (_vertices_size < num_used_vertices) {
00601 if (_vertices_size == 0) {
00602 _vertices_size = 1;
00603 }
00604 while (_vertices_size < num_used_vertices) {
00605 _vertices_size *= 2;
00606 }
00607 if (_vertices != (GLVertex *)NULL) {
00608 PANDA_FREE_ARRAY(_vertices);
00609 }
00610 _vertices = (GLVertex *)PANDA_MALLOC_ARRAY(_vertices_size * sizeof(GLVertex));
00611 }
00612
00613 GeomVertexReader rcolor, rnormal;
00614
00615
00616 GenTexcoordFunc *texgen_func[MAX_TEXTURE_STAGES];
00617 TexCoordData tcdata[MAX_TEXTURE_STAGES];
00618
00619 const TexGenAttrib *target_tex_gen = DCAST(TexGenAttrib, _target_rs->get_attrib_def(TexGenAttrib::get_class_slot()));
00620 const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
00621
00622 int max_stage_index = _target_texture->get_num_on_ff_stages();
00623 for (int si = 0; si < max_stage_index; ++si) {
00624 TextureStage *stage = _target_texture->get_on_ff_stage(si);
00625
00626 switch (target_tex_gen->get_mode(stage)) {
00627 case TexGenAttrib::M_eye_sphere_map:
00628 tcdata[si]._r1 = GeomVertexReader(data_reader, InternalName::get_normal(),
00629 force);
00630 tcdata[si]._r2 = GeomVertexReader(data_reader, InternalName::get_vertex(),
00631 force);
00632 texgen_func[si] = &texgen_sphere_map;
00633 tcdata[si]._mat = _internal_transform->get_mat();
00634 break;
00635
00636 case TexGenAttrib::M_eye_position:
00637 tcdata[si]._r1 = GeomVertexReader(data_reader, InternalName::get_vertex(),
00638 force);
00639 texgen_func[si] = &texgen_texmat;
00640 {
00641 CPT(TransformState) eye_transform =
00642 _cs_transform->invert_compose(_internal_transform);
00643 tcdata[si]._mat = eye_transform->get_mat();
00644 }
00645 if (target_tex_matrix->has_stage(stage)) {
00646 tcdata[si]._mat = tcdata[si]._mat * target_tex_matrix->get_mat(stage);
00647 }
00648 break;
00649
00650 case TexGenAttrib::M_world_position:
00651 tcdata[si]._r1 = GeomVertexReader(data_reader, InternalName::get_vertex(),
00652 force);
00653 texgen_func[si] = &texgen_texmat;
00654 {
00655 CPT(TransformState) render_transform =
00656 _cs_transform->compose(_scene_setup->get_world_transform());
00657 CPT(TransformState) world_inv_transform =
00658 render_transform->invert_compose(_internal_transform);
00659 tcdata[si]._mat = world_inv_transform->get_mat();
00660 }
00661 if (target_tex_matrix->has_stage(stage)) {
00662 tcdata[si]._mat = tcdata[si]._mat * target_tex_matrix->get_mat(stage);
00663 }
00664 break;
00665
00666 default:
00667
00668 tcdata[si]._r1 = GeomVertexReader(data_reader, stage->get_texcoord_name(),
00669 force);
00670 texgen_func[si] = &texgen_simple;
00671 if (target_tex_matrix->has_stage(stage)) {
00672 texgen_func[si] = &texgen_texmat;
00673 tcdata[si]._mat = target_tex_matrix->get_mat(stage);
00674 }
00675
00676 break;
00677 }
00678 tcdata[si]._r1.set_row_unsafe(_min_vertex);
00679 tcdata[si]._r2.set_row_unsafe(_min_vertex);
00680 if (!tcdata[si]._r1.has_column()) {
00681 texgen_func[si] = &texgen_null;
00682 }
00683 }
00684
00685 bool needs_color = false;
00686 if (_vertex_colors_enabled) {
00687 rcolor = GeomVertexReader(data_reader, InternalName::get_color(), force);
00688 rcolor.set_row_unsafe(_min_vertex);
00689 needs_color = rcolor.has_column();
00690 }
00691
00692 if (!needs_color) {
00693 const LColor &d = _scene_graph_color;
00694 const LColor &s = _current_color_scale;
00695 _c->current_color.v[0] = d[0] * s[0];
00696 _c->current_color.v[1] = d[1] * s[1];
00697 _c->current_color.v[2] = d[2] * s[2];
00698 _c->current_color.v[3] = d[3] * s[3];
00699 }
00700
00701 bool needs_normal = false;
00702 if (_c->lighting_enabled) {
00703 rnormal = GeomVertexReader(data_reader, InternalName::get_normal(), force);
00704 rnormal.set_row_unsafe(_min_vertex);
00705 needs_normal = rnormal.has_column();
00706 }
00707
00708 GeomVertexReader rvertex(data_reader, InternalName::get_vertex(), force);
00709 rvertex.set_row_unsafe(_min_vertex);
00710
00711 if (!rvertex.has_column()) {
00712
00713 return false;
00714 }
00715
00716 if (!needs_color && _color_material_flags) {
00717 if (_color_material_flags & CMF_ambient) {
00718 _c->materials[0].ambient = _c->current_color;
00719 _c->materials[1].ambient = _c->current_color;
00720 }
00721 if (_color_material_flags & CMF_diffuse) {
00722 _c->materials[0].diffuse = _c->current_color;
00723 _c->materials[1].diffuse = _c->current_color;
00724 }
00725 }
00726
00727 if (_texturing_state != 0 && _texture_replace) {
00728
00729
00730 needs_color = false;
00731 needs_normal = false;
00732 }
00733
00734 bool lighting_enabled = (needs_normal && _c->lighting_enabled);
00735
00736 for (i = 0; i < num_used_vertices; ++i) {
00737 GLVertex *v = &_vertices[i];
00738 const LVecBase4 &d = rvertex.get_data4();
00739
00740 v->coord.v[0] = d[0];
00741 v->coord.v[1] = d[1];
00742 v->coord.v[2] = d[2];
00743 v->coord.v[3] = d[3];
00744
00745
00746 for (int si = 0; si < max_stage_index; ++si) {
00747 LTexCoord d;
00748 (*texgen_func[si])(v->tex_coord[si], tcdata[si]);
00749 }
00750
00751 if (needs_color) {
00752 const LColor &d = rcolor.get_data4();
00753 const LColor &s = _current_color_scale;
00754 _c->current_color.v[0] = d[0] * s[0];
00755 _c->current_color.v[1] = d[1] * s[1];
00756 _c->current_color.v[2] = d[2] * s[2];
00757 _c->current_color.v[3] = d[3] * s[3];
00758
00759 if (_color_material_flags) {
00760 if (_color_material_flags & CMF_ambient) {
00761 _c->materials[0].ambient = _c->current_color;
00762 _c->materials[1].ambient = _c->current_color;
00763 }
00764 if (_color_material_flags & CMF_diffuse) {
00765 _c->materials[0].diffuse = _c->current_color;
00766 _c->materials[1].diffuse = _c->current_color;
00767 }
00768 }
00769 }
00770
00771 v->color = _c->current_color;
00772
00773 if (lighting_enabled) {
00774 const LVecBase3 &d = rnormal.get_data3();
00775 _c->current_normal.v[0] = d[0];
00776 _c->current_normal.v[1] = d[1];
00777 _c->current_normal.v[2] = d[2];
00778 _c->current_normal.v[3] = 0.0f;
00779
00780 gl_vertex_transform(_c, v);
00781 gl_shade_vertex(_c, v);
00782
00783 } else {
00784 gl_vertex_transform(_c, v);
00785 }
00786
00787 if (v->clip_code == 0) {
00788 gl_transform_to_viewport(_c, v);
00789 }
00790
00791 v->edge_flag = 1;
00792 }
00793
00794
00795
00796
00797 int depth_write_state = 0;
00798 const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot()));
00799 if (target_depth_write->get_mode() != DepthWriteAttrib::M_on) {
00800 depth_write_state = 1;
00801 }
00802
00803 int color_write_state = 0;
00804
00805 const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot()));
00806 unsigned int color_channels =
00807 target_color_write->get_channels() & _color_write_mask;
00808 if (color_channels != ColorWriteAttrib::C_all) {
00809
00810 int op_a = get_color_blend_op(ColorBlendAttrib::O_one);
00811 int op_b = get_color_blend_op(ColorBlendAttrib::O_zero);
00812 _c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
00813 color_write_state = 2;
00814 }
00815
00816 const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
00817 switch (target_transparency->get_mode()) {
00818 case TransparencyAttrib::M_alpha:
00819 case TransparencyAttrib::M_dual:
00820 color_write_state = 1;
00821 if (color_channels != ColorWriteAttrib::C_all) {
00822
00823 int op_a = get_color_blend_op(ColorBlendAttrib::O_incoming_alpha);
00824 int op_b = get_color_blend_op(ColorBlendAttrib::O_one_minus_incoming_alpha);
00825 _c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
00826 color_write_state = 2;
00827 }
00828 break;
00829
00830 default:
00831 break;
00832 }
00833
00834 const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
00835 if (target_color_blend->get_mode() == ColorBlendAttrib::M_add) {
00836
00837
00838 int op_a = get_color_blend_op(target_color_blend->get_operand_a());
00839 int op_b = get_color_blend_op(target_color_blend->get_operand_b());
00840 _c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
00841 LColor c = target_color_blend->get_color();
00842 _c->zb->blend_r = (int)(c[0] * ZB_POINT_RED_MAX);
00843 _c->zb->blend_g = (int)(c[1] * ZB_POINT_GREEN_MAX);
00844 _c->zb->blend_b = (int)(c[2] * ZB_POINT_BLUE_MAX);
00845 _c->zb->blend_a = (int)(c[3] * ZB_POINT_ALPHA_MAX);
00846
00847 color_write_state = 2;
00848 }
00849
00850 if (color_channels == ColorWriteAttrib::C_off) {
00851 color_write_state = 3;
00852 }
00853
00854 int alpha_test_state = 0;
00855 const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
00856 switch (target_alpha_test->get_mode()) {
00857 case AlphaTestAttrib::M_none:
00858 case AlphaTestAttrib::M_never:
00859 case AlphaTestAttrib::M_always:
00860 case AlphaTestAttrib::M_equal:
00861 case AlphaTestAttrib::M_not_equal:
00862 alpha_test_state = 0;
00863 break;
00864
00865 case AlphaTestAttrib::M_less:
00866 case AlphaTestAttrib::M_less_equal:
00867 alpha_test_state = 1;
00868 _c->zb->reference_alpha = (int)(target_alpha_test->get_reference_alpha() * ZB_POINT_ALPHA_MAX);
00869 break;
00870
00871 case AlphaTestAttrib::M_greater:
00872 case AlphaTestAttrib::M_greater_equal:
00873 alpha_test_state = 2;
00874 _c->zb->reference_alpha = (int)(target_alpha_test->get_reference_alpha() * ZB_POINT_ALPHA_MAX);
00875 break;
00876 }
00877
00878 int depth_test_state = 1;
00879 _c->depth_test = 1;
00880 const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot()));
00881 if (target_depth_test->get_mode() == DepthTestAttrib::M_none) {
00882 depth_test_state = 0;
00883 _c->depth_test = 0;
00884 }
00885
00886 const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot()));
00887 ShadeModelAttrib::Mode shade_model = target_shade_model->get_mode();
00888 if (!needs_normal && !needs_color) {
00889
00890
00891 shade_model = ShadeModelAttrib::M_flat;
00892 }
00893 int shade_model_state = 2;
00894 _c->smooth_shade_model = true;
00895
00896 if (shade_model == ShadeModelAttrib::M_flat) {
00897 _c->smooth_shade_model = false;
00898 shade_model_state = 1;
00899 if (_c->current_color.v[0] == 1.0f &&
00900 _c->current_color.v[1] == 1.0f &&
00901 _c->current_color.v[2] == 1.0f &&
00902 _c->current_color.v[3] == 1.0f) {
00903 shade_model_state = 0;
00904 }
00905 }
00906
00907 int texturing_state = _texturing_state;
00908 int texfilter_state = 0;
00909 if (texturing_state > 0) {
00910 texfilter_state = _texfilter_state;
00911
00912 if (texturing_state < 3 &&
00913 (_c->matrix_model_projection_no_w_transform || _filled_flat)) {
00914
00915
00916
00917 texturing_state = 1;
00918 }
00919
00920 if (_texture_replace) {
00921
00922
00923 shade_model_state = 0;
00924 }
00925 }
00926
00927 _c->zb_fill_tri = fill_tri_funcs[depth_write_state][color_write_state][alpha_test_state][depth_test_state][texfilter_state][shade_model_state][texturing_state];
00928
00929 #ifdef DO_PSTATS
00930 pixel_count_white_untextured = 0;
00931 pixel_count_flat_untextured = 0;
00932 pixel_count_smooth_untextured = 0;
00933 pixel_count_white_textured = 0;
00934 pixel_count_flat_textured = 0;
00935 pixel_count_smooth_textured = 0;
00936 pixel_count_white_perspective = 0;
00937 pixel_count_flat_perspective = 0;
00938 pixel_count_smooth_perspective = 0;
00939 pixel_count_smooth_multitex2 = 0;
00940 pixel_count_smooth_multitex3 = 0;
00941 #endif // DO_PSTATS
00942
00943 return true;
00944 }
00945
00946
00947
00948
00949
00950
00951 bool TinyGraphicsStateGuardian::
00952 draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
00953 PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
00954
00955 #ifndef NDEBUG
00956 if (tinydisplay_cat.is_spam()) {
00957 tinydisplay_cat.spam() << "draw_triangles: " << *(reader->get_object()) << "\n";
00958 }
00959 #endif // NDEBUG
00960
00961 int num_vertices = reader->get_num_vertices();
00962 _vertices_tri_pcollector.add_level(num_vertices);
00963
00964 if (reader->is_indexed()) {
00965 switch (reader->get_index_type()) {
00966 case Geom::NT_uint8:
00967 {
00968 PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
00969 if (index == NULL) {
00970 return false;
00971 }
00972 for (int i = 0; i < num_vertices; i += 3) {
00973 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
00974 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
00975 GLVertex *v2 = &_vertices[index[i + 2] - _min_vertex];
00976 gl_draw_triangle(_c, v0, v1, v2);
00977 }
00978 }
00979 break;
00980
00981 case Geom::NT_uint16:
00982 {
00983 PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
00984 if (index == NULL) {
00985 return false;
00986 }
00987 for (int i = 0; i < num_vertices; i += 3) {
00988 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
00989 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
00990 GLVertex *v2 = &_vertices[index[i + 2] - _min_vertex];
00991 gl_draw_triangle(_c, v0, v1, v2);
00992 }
00993 }
00994 break;
00995
00996 case Geom::NT_uint32:
00997 {
00998 PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
00999 if (index == NULL) {
01000 return false;
01001 }
01002 for (int i = 0; i < num_vertices; i += 3) {
01003 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
01004 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
01005 GLVertex *v2 = &_vertices[index[i + 2] - _min_vertex];
01006 gl_draw_triangle(_c, v0, v1, v2);
01007 }
01008 }
01009 break;
01010
01011 default:
01012 break;
01013 }
01014
01015 } else {
01016 int delta = reader->get_first_vertex() - _min_vertex;
01017 for (int vi = 0; vi < num_vertices; vi += 3) {
01018 GLVertex *v0 = &_vertices[vi + delta];
01019 GLVertex *v1 = &_vertices[vi + delta + 1];
01020 GLVertex *v2 = &_vertices[vi + delta + 2];
01021 gl_draw_triangle(_c, v0, v1, v2);
01022 }
01023 }
01024
01025 return true;
01026 }
01027
01028
01029
01030
01031
01032
01033 bool TinyGraphicsStateGuardian::
01034 draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
01035 PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
01036
01037 #ifndef NDEBUG
01038 if (tinydisplay_cat.is_spam()) {
01039 tinydisplay_cat.spam() << "draw_tristrips: " << *(reader->get_object()) << "\n";
01040 }
01041 #endif // NDEBUG
01042
01043
01044
01045 CPTA_int ends = reader->get_ends();
01046
01047 _primitive_batches_tristrip_pcollector.add_level(ends.size());
01048 if (reader->is_indexed()) {
01049 unsigned int start = 0;
01050 for (size_t i = 0; i < ends.size(); i++) {
01051 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01052
01053 int end = ends[i];
01054 nassertr(end - start >= 3, false);
01055
01056 switch (reader->get_index_type()) {
01057 case Geom::NT_uint8:
01058 {
01059 PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
01060 if (index == NULL) {
01061 return false;
01062 }
01063 GLVertex *v0 = &_vertices[index[start] - _min_vertex];
01064 GLVertex *v1 = &_vertices[index[start + 1] - _min_vertex];
01065
01066 bool reversed = false;
01067 for (int vi = start + 2; vi < end; ++vi) {
01068 GLVertex *v2 = &_vertices[index[vi] - _min_vertex];
01069 if (reversed) {
01070 gl_draw_triangle(_c, v1, v0, v2);
01071 reversed = false;
01072 } else {
01073 gl_draw_triangle(_c, v0, v1, v2);
01074 reversed = true;
01075 }
01076 v0 = v1;
01077 v1 = v2;
01078 }
01079 }
01080 break;
01081
01082 case Geom::NT_uint16:
01083 {
01084 PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
01085 if (index == NULL) {
01086 return false;
01087 }
01088 GLVertex *v0 = &_vertices[index[start] - _min_vertex];
01089 GLVertex *v1 = &_vertices[index[start + 1] - _min_vertex];
01090
01091 bool reversed = false;
01092 for (int vi = start + 2; vi < end; ++vi) {
01093 GLVertex *v2 = &_vertices[index[vi] - _min_vertex];
01094 if (reversed) {
01095 gl_draw_triangle(_c, v1, v0, v2);
01096 reversed = false;
01097 } else {
01098 gl_draw_triangle(_c, v0, v1, v2);
01099 reversed = true;
01100 }
01101 v0 = v1;
01102 v1 = v2;
01103 }
01104 }
01105 break;
01106
01107 case Geom::NT_uint32:
01108 {
01109 PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
01110 if (index == NULL) {
01111 return false;
01112 }
01113 GLVertex *v0 = &_vertices[index[start] - _min_vertex];
01114 GLVertex *v1 = &_vertices[index[start + 1] - _min_vertex];
01115
01116 bool reversed = false;
01117 for (int vi = start + 2; vi < end; ++vi) {
01118 GLVertex *v2 = &_vertices[index[vi] - _min_vertex];
01119 if (reversed) {
01120 gl_draw_triangle(_c, v1, v0, v2);
01121 reversed = false;
01122 } else {
01123 gl_draw_triangle(_c, v0, v1, v2);
01124 reversed = true;
01125 }
01126 v0 = v1;
01127 v1 = v2;
01128 }
01129 }
01130 break;
01131 }
01132
01133 start = ends[i] + 2;
01134 }
01135 } else {
01136 unsigned int start = 0;
01137 int delta = reader->get_first_vertex() - _min_vertex;
01138 for (size_t i = 0; i < ends.size(); i++) {
01139 _vertices_tristrip_pcollector.add_level(ends[i] - start);
01140
01141 int end = ends[i];
01142 nassertr(end - start >= 3, false);
01143 GLVertex *v0 = &_vertices[start + delta];
01144 GLVertex *v1 = &_vertices[start + delta + 1];
01145
01146 bool reversed = false;
01147 for (int vi = start + 2; vi < end; ++vi) {
01148 GLVertex *v2 = &_vertices[vi + delta];
01149 if (reversed) {
01150 gl_draw_triangle(_c, v1, v0, v2);
01151 reversed = false;
01152 } else {
01153 gl_draw_triangle(_c, v0, v1, v2);
01154 reversed = true;
01155 }
01156 v0 = v1;
01157 v1 = v2;
01158 }
01159 start = ends[i] + 2;
01160 }
01161 }
01162
01163 return true;
01164 }
01165
01166
01167
01168
01169
01170
01171 bool TinyGraphicsStateGuardian::
01172 draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
01173 PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
01174 #ifndef NDEBUG
01175 if (tinydisplay_cat.is_spam()) {
01176 tinydisplay_cat.spam() << "draw_lines: " << *(reader->get_object()) << "\n";
01177 }
01178 #endif // NDEBUG
01179
01180 int num_vertices = reader->get_num_vertices();
01181 _vertices_other_pcollector.add_level(num_vertices);
01182
01183 if (reader->is_indexed()) {
01184 switch (reader->get_index_type()) {
01185 case Geom::NT_uint8:
01186 {
01187 PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
01188 if (index == NULL) {
01189 return false;
01190 }
01191 for (int i = 0; i < num_vertices; i += 2) {
01192 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
01193 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
01194 gl_draw_line(_c, v0, v1);
01195 }
01196 }
01197 break;
01198
01199 case Geom::NT_uint16:
01200 {
01201 PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
01202 if (index == NULL) {
01203 return false;
01204 }
01205 for (int i = 0; i < num_vertices; i += 2) {
01206 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
01207 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
01208 gl_draw_line(_c, v0, v1);
01209 }
01210 }
01211 break;
01212
01213 case Geom::NT_uint32:
01214 {
01215 PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
01216 if (index == NULL) {
01217 return false;
01218 }
01219 for (int i = 0; i < num_vertices; i += 2) {
01220 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
01221 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
01222 gl_draw_line(_c, v0, v1);
01223 }
01224 }
01225 break;
01226
01227 default:
01228 break;
01229 }
01230
01231 } else {
01232 int delta = reader->get_first_vertex() - _min_vertex;
01233 for (int vi = 0; vi < num_vertices; vi += 2) {
01234 GLVertex *v0 = &_vertices[vi + delta];
01235 GLVertex *v1 = &_vertices[vi + delta + 1];
01236 gl_draw_line(_c, v0, v1);
01237 }
01238 }
01239
01240 return true;
01241 }
01242
01243
01244
01245
01246
01247
01248 bool TinyGraphicsStateGuardian::
01249 draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
01250 PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
01251 #ifndef NDEBUG
01252 if (tinydisplay_cat.is_spam()) {
01253 tinydisplay_cat.spam() << "draw_points: " << *(reader->get_object()) << "\n";
01254 }
01255 #endif // NDEBUG
01256
01257 int num_vertices = reader->get_num_vertices();
01258 _vertices_other_pcollector.add_level(num_vertices);
01259
01260 if (reader->is_indexed()) {
01261 switch (reader->get_index_type()) {
01262 case Geom::NT_uint8:
01263 {
01264 PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
01265 if (index == NULL) {
01266 return false;
01267 }
01268 for (int i = 0; i < num_vertices; ++i) {
01269 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
01270 gl_draw_point(_c, v0);
01271 }
01272 }
01273 break;
01274
01275 case Geom::NT_uint16:
01276 {
01277 PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
01278 if (index == NULL) {
01279 return false;
01280 }
01281 for (int i = 0; i < num_vertices; ++i) {
01282 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
01283 gl_draw_point(_c, v0);
01284 }
01285 }
01286 break;
01287
01288 case Geom::NT_uint32:
01289 {
01290 PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
01291 if (index == NULL) {
01292 return false;
01293 }
01294 for (int i = 0; i < num_vertices; ++i) {
01295 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
01296 gl_draw_point(_c, v0);
01297 }
01298 }
01299 break;
01300
01301 default:
01302 break;
01303 }
01304
01305 } else {
01306 int delta = reader->get_first_vertex() - _min_vertex;
01307 for (int vi = 0; vi < num_vertices; ++vi) {
01308 GLVertex *v0 = &_vertices[vi + delta];
01309 gl_draw_point(_c, v0);
01310 }
01311 }
01312
01313 return true;
01314 }
01315
01316
01317
01318
01319
01320
01321
01322
01323 void TinyGraphicsStateGuardian::
01324 end_draw_primitives() {
01325
01326 #ifdef DO_PSTATS
01327 _pixel_count_white_untextured_pcollector.add_level(pixel_count_white_untextured);
01328 _pixel_count_flat_untextured_pcollector.add_level(pixel_count_flat_untextured);
01329 _pixel_count_smooth_untextured_pcollector.add_level(pixel_count_smooth_untextured);
01330 _pixel_count_white_textured_pcollector.add_level(pixel_count_white_textured);
01331 _pixel_count_flat_textured_pcollector.add_level(pixel_count_flat_textured);
01332 _pixel_count_smooth_textured_pcollector.add_level(pixel_count_smooth_textured);
01333 _pixel_count_white_perspective_pcollector.add_level(pixel_count_white_perspective);
01334 _pixel_count_flat_perspective_pcollector.add_level(pixel_count_flat_perspective);
01335 _pixel_count_smooth_perspective_pcollector.add_level(pixel_count_smooth_perspective);
01336 _pixel_count_smooth_multitex2_pcollector.add_level(pixel_count_smooth_multitex2);
01337 _pixel_count_smooth_multitex3_pcollector.add_level(pixel_count_smooth_multitex3);
01338 #endif // DO_PSTATS
01339
01340 GraphicsStateGuardian::end_draw_primitives();
01341 }
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352 bool TinyGraphicsStateGuardian::
01353 framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
01354 const RenderBuffer &rb) {
01355 nassertr(tex != NULL && dr != NULL, false);
01356
01357 int xo, yo, w, h;
01358 dr->get_region_pixels_i(xo, yo, w, h);
01359
01360 tex->setup_2d_texture(w, h, Texture::T_unsigned_byte, Texture::F_rgba);
01361
01362 int view = dr->get_tex_view_offset();
01363 TextureContext *tc = tex->prepare_now(view, get_prepared_objects(), this);
01364 nassertr(tc != (TextureContext *)NULL, false);
01365 TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
01366
01367 GLTexture *gltex = >c->_gltex;
01368 if (!setup_gltex(gltex, tex->get_x_size(), tex->get_y_size(), 1)) {
01369 return false;
01370 }
01371 LColor border_color = tex->get_border_color();
01372 gltex->border_color.v[0] = border_color[0];
01373 gltex->border_color.v[1] = border_color[1];
01374 gltex->border_color.v[2] = border_color[2];
01375 gltex->border_color.v[3] = border_color[3];
01376
01377 PIXEL *ip = gltex->levels[0].pixmap + gltex->xsize * gltex->ysize;
01378 PIXEL *fo = _c->zb->pbuf + xo + yo * _c->zb->linesize / PSZB;
01379 for (int y = 0; y < gltex->ysize; ++y) {
01380 ip -= gltex->xsize;
01381 memcpy(ip, fo, gltex->xsize * PSZB);
01382 fo += _c->zb->linesize / PSZB;
01383 }
01384
01385 gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4);
01386 gtc->mark_loaded();
01387 gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
01388
01389 return true;
01390 }
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403 bool TinyGraphicsStateGuardian::
01404 framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
01405 const RenderBuffer &rb) {
01406 nassertr(tex != NULL && dr != NULL, false);
01407
01408 int xo, yo, w, h;
01409 dr->get_region_pixels_i(xo, yo, w, h);
01410
01411 Texture::TextureType texture_type;
01412 int z_size;
01413 if (z >= 0) {
01414 texture_type = Texture::TT_cube_map;
01415 z_size = 6;
01416 } else {
01417 texture_type = Texture::TT_2d_texture;
01418 z_size = 1;
01419 }
01420
01421 Texture::ComponentType component_type = Texture::T_unsigned_byte;
01422 Texture::Format format = Texture::F_rgba;
01423
01424 if (tex->get_x_size() != w || tex->get_y_size() != h ||
01425 tex->get_z_size() != z_size ||
01426 tex->get_component_type() != component_type ||
01427 tex->get_format() != format ||
01428 tex->get_texture_type() != texture_type) {
01429
01430 tex->setup_texture(texture_type, w, h, z_size,
01431 component_type, format);
01432 }
01433
01434 unsigned char *image_ptr = tex->modify_ram_image();
01435 size_t image_size = tex->get_ram_image_size();
01436 if (z >= 0) {
01437 nassertr(z < tex->get_z_size(), false);
01438 image_size = tex->get_expected_ram_page_size();
01439 image_ptr += z * image_size;
01440 }
01441
01442 PIXEL *ip = (PIXEL *)(image_ptr + image_size);
01443 PIXEL *fo = _c->zb->pbuf + xo + yo * _c->zb->linesize / PSZB;
01444 for (int y = 0; y < h; ++y) {
01445 ip -= w;
01446 #ifndef WORDS_BIGENDIAN
01447
01448 memcpy(ip, fo, w * PSZB);
01449 #else
01450
01451 const char *source = (const char *)fo;
01452 const char *stop = (const char *)fo + w * PSZB;
01453 char *dest = (char *)ip;
01454 while (source < stop) {
01455 char b = source[0];
01456 char g = source[1];
01457 char r = source[2];
01458 char a = source[3];
01459 dest[0] = a;
01460 dest[1] = r;
01461 dest[2] = g;
01462 dest[3] = b;
01463 dest += 4;
01464 source += 4;
01465 }
01466 #endif
01467 fo += _c->zb->linesize / PSZB;
01468 }
01469
01470 return true;
01471 }
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490 void TinyGraphicsStateGuardian::
01491 set_state_and_transform(const RenderState *target,
01492 const TransformState *transform) {
01493 #ifndef NDEBUG
01494 if (tinydisplay_cat.is_spam()) {
01495 tinydisplay_cat.spam()
01496 << "Setting GSG state to " << (void *)target << ":\n";
01497 target->write(tinydisplay_cat.spam(false), 2);
01498 transform->write(tinydisplay_cat.spam(false), 2);
01499 }
01500 #endif
01501
01502 _state_pcollector.add_level(1);
01503 PStatTimer timer1(_draw_set_state_pcollector);
01504
01505 if (transform != _internal_transform) {
01506 PStatTimer timer(_draw_set_state_transform_pcollector);
01507 _state_pcollector.add_level(1);
01508 _internal_transform = transform;
01509 do_issue_transform();
01510 }
01511
01512 if (target == _state_rs && (_state_mask | _inv_state_mask).is_all_on()) {
01513 return;
01514 }
01515 _target_rs = target;
01516
01517 int color_slot = ColorAttrib::get_class_slot();
01518 int color_scale_slot = ColorScaleAttrib::get_class_slot();
01519 if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) ||
01520 _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) ||
01521 !_state_mask.get_bit(color_slot) ||
01522 !_state_mask.get_bit(color_scale_slot)) {
01523 PStatTimer timer(_draw_set_state_color_pcollector);
01524 do_issue_color();
01525 do_issue_color_scale();
01526 _state_mask.set_bit(color_slot);
01527 _state_mask.set_bit(color_scale_slot);
01528 }
01529
01530 int cull_face_slot = CullFaceAttrib::get_class_slot();
01531 if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) ||
01532 !_state_mask.get_bit(cull_face_slot)) {
01533 PStatTimer timer(_draw_set_state_cull_face_pcollector);
01534 do_issue_cull_face();
01535 _state_mask.set_bit(cull_face_slot);
01536 }
01537
01538 int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
01539 if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
01540 !_state_mask.get_bit(depth_offset_slot)) {
01541
01542 do_issue_depth_offset();
01543 _state_mask.set_bit(depth_offset_slot);
01544 }
01545
01546 int rescale_normal_slot = RescaleNormalAttrib::get_class_slot();
01547 if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) ||
01548 !_state_mask.get_bit(rescale_normal_slot)) {
01549 PStatTimer timer(_draw_set_state_rescale_normal_pcollector);
01550 do_issue_rescale_normal();
01551 _state_mask.set_bit(rescale_normal_slot);
01552 }
01553
01554 int render_mode_slot = RenderModeAttrib::get_class_slot();
01555 if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) ||
01556 !_state_mask.get_bit(render_mode_slot)) {
01557 PStatTimer timer(_draw_set_state_render_mode_pcollector);
01558 do_issue_render_mode();
01559 _state_mask.set_bit(render_mode_slot);
01560 }
01561
01562 int texture_slot = TextureAttrib::get_class_slot();
01563 if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
01564 !_state_mask.get_bit(texture_slot)) {
01565 PStatTimer timer(_draw_set_state_texture_pcollector);
01566 determine_target_texture();
01567 do_issue_texture();
01568 _state_mask.set_bit(texture_slot);
01569 }
01570
01571 int material_slot = MaterialAttrib::get_class_slot();
01572 if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) ||
01573 !_state_mask.get_bit(material_slot)) {
01574 PStatTimer timer(_draw_set_state_material_pcollector);
01575 do_issue_material();
01576 _state_mask.set_bit(material_slot);
01577 }
01578
01579 int light_slot = LightAttrib::get_class_slot();
01580 if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) ||
01581 !_state_mask.get_bit(light_slot)) {
01582 PStatTimer timer(_draw_set_state_light_pcollector);
01583 do_issue_light();
01584 _state_mask.set_bit(light_slot);
01585 }
01586
01587 int scissor_slot = ScissorAttrib::get_class_slot();
01588 if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) ||
01589 !_state_mask.get_bit(scissor_slot)) {
01590 PStatTimer timer(_draw_set_state_scissor_pcollector);
01591 do_issue_scissor();
01592 _state_mask.set_bit(scissor_slot);
01593 }
01594
01595 _state_rs = _target_rs;
01596 }
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611 TextureContext *TinyGraphicsStateGuardian::
01612 prepare_texture(Texture *tex, int view) {
01613 switch (tex->get_texture_type()) {
01614 case Texture::TT_1d_texture:
01615 case Texture::TT_2d_texture:
01616
01617 break;
01618
01619 default:
01620
01621 tinydisplay_cat.info()
01622 << "Not loading texture " << tex->get_name() << ": "
01623 << tex->get_texture_type() << "\n";
01624 return NULL;
01625 }
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639 TinyTextureContext *gtc = new TinyTextureContext(_prepared_objects, tex, view);
01640
01641 return gtc;
01642 }
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660 bool TinyGraphicsStateGuardian::
01661 update_texture(TextureContext *tc, bool force) {
01662 apply_texture(tc);
01663
01664 TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
01665
01666 GLTexture *gltex = >c->_gltex;
01667
01668 if (gtc->was_image_modified() || gltex->num_levels == 0) {
01669
01670 bool okflag = upload_texture(gtc, force);
01671 if (!okflag) {
01672 tinydisplay_cat.error()
01673 << "Could not load " << *gtc->get_texture() << "\n";
01674 return false;
01675 }
01676 }
01677 gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
01678
01679 return true;
01680 }
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698 bool TinyGraphicsStateGuardian::
01699 update_texture(TextureContext *tc, bool force, int stage_index) {
01700 if (!update_texture(tc, force)) {
01701 return false;
01702 }
01703
01704 TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
01705 GLTexture *gltex = >c->_gltex;
01706
01707 _c->current_textures[stage_index] = gltex;
01708
01709 ZTextureDef *texture_def = &_c->zb->current_textures[stage_index];
01710 texture_def->levels = gltex->levels;
01711 texture_def->s_max = gltex->s_max;
01712 texture_def->t_max = gltex->t_max;
01713
01714 const V4 &bc = gltex->border_color;
01715 int r = (int)(bc.v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN)
01716 + ZB_POINT_RED_MIN);
01717 int g = (int)(bc.v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN)
01718 + ZB_POINT_GREEN_MIN);
01719 int b = (int)(bc.v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN)
01720 + ZB_POINT_BLUE_MIN);
01721 int a = (int)(bc.v[3] * (ZB_POINT_ALPHA_MAX - ZB_POINT_ALPHA_MIN)
01722 + ZB_POINT_ALPHA_MIN);
01723 texture_def->border_color = RGBA_TO_PIXEL(r, g, b, a);
01724
01725 return true;
01726 }
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736 void TinyGraphicsStateGuardian::
01737 release_texture(TextureContext *tc) {
01738 TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
01739
01740 _texturing_state = 0;
01741
01742 GLTexture *gltex = >c->_gltex;
01743 if (gltex->allocated_buffer != NULL) {
01744 nassertv(gltex->num_levels != 0);
01745 TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
01746 PANDA_FREE_ARRAY(gltex->allocated_buffer);
01747 gltex->allocated_buffer = NULL;
01748 gltex->total_bytecount = 0;
01749 gltex->num_levels = 0;
01750 } else {
01751 nassertv(gltex->num_levels == 0);
01752 }
01753
01754 gtc->dequeue_lru();
01755
01756 delete gtc;
01757 }
01758
01759
01760
01761
01762
01763
01764 void TinyGraphicsStateGuardian::
01765 do_issue_light() {
01766
01767
01768 LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
01769
01770 int num_enabled = 0;
01771 int num_on_lights = 0;
01772
01773 const LightAttrib *target_light = DCAST(LightAttrib, _target_rs->get_attrib_def(LightAttrib::get_class_slot()));
01774 if (display_cat.is_spam()) {
01775 display_cat.spam()
01776 << "do_issue_light: " << target_light << "\n";
01777 }
01778
01779
01780 clear_light_state();
01781
01782
01783 if (target_light != (LightAttrib *)NULL) {
01784 CPT(LightAttrib) new_light = target_light->filter_to_max(_max_lights);
01785 if (display_cat.is_spam()) {
01786 new_light->write(display_cat.spam(false), 2);
01787 }
01788
01789 num_on_lights = new_light->get_num_on_lights();
01790 for (int li = 0; li < num_on_lights; li++) {
01791 NodePath light = new_light->get_on_light(li);
01792 nassertv(!light.is_empty());
01793 Light *light_obj = light.node()->as_light();
01794 nassertv(light_obj != (Light *)NULL);
01795
01796 _lighting_enabled = true;
01797 _c->lighting_enabled = true;
01798
01799 if (light_obj->get_type() == AmbientLight::get_class_type()) {
01800
01801 cur_ambient_light += light_obj->get_color();
01802
01803 } else {
01804
01805 light_obj->bind(this, light, num_enabled);
01806 num_enabled++;
01807
01808
01809
01810 GLLight *gl_light = _c->first_light;
01811 nassertv(gl_light != NULL);
01812 const LColor &diffuse = light_obj->get_color();
01813 gl_light->diffuse.v[0] = diffuse[0];
01814 gl_light->diffuse.v[1] = diffuse[1];
01815 gl_light->diffuse.v[2] = diffuse[2];
01816 gl_light->diffuse.v[3] = diffuse[3];
01817 }
01818 }
01819 }
01820
01821 _c->ambient_light_model.v[0] = cur_ambient_light[0];
01822 _c->ambient_light_model.v[1] = cur_ambient_light[1];
01823 _c->ambient_light_model.v[2] = cur_ambient_light[2];
01824 _c->ambient_light_model.v[3] = cur_ambient_light[3];
01825
01826
01827
01828 _transform_stale = true;
01829 }
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839 void TinyGraphicsStateGuardian::
01840 bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
01841 pair<Lights::iterator, bool> lookup = _plights.insert(Lights::value_type(light, GLLight()));
01842 GLLight *gl_light = &(*lookup.first).second;
01843 if (lookup.second) {
01844
01845 memset(gl_light, 0, sizeof(GLLight));
01846
01847 const LColor &specular = light_obj->get_specular_color();
01848 gl_light->specular.v[0] = specular[0];
01849 gl_light->specular.v[1] = specular[1];
01850 gl_light->specular.v[2] = specular[2];
01851 gl_light->specular.v[3] = specular[3];
01852
01853
01854
01855 CPT(TransformState) render_transform =
01856 _cs_transform->compose(_scene_setup->get_world_transform());
01857
01858 CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
01859 CPT(TransformState) net_transform = render_transform->compose(transform);
01860
01861 LPoint3 pos = light_obj->get_point() * net_transform->get_mat();
01862 gl_light->position.v[0] = pos[0];
01863 gl_light->position.v[1] = pos[1];
01864 gl_light->position.v[2] = pos[2];
01865 gl_light->position.v[3] = 1.0f;
01866
01867
01868 gl_light->spot_exponent = 0.0f;
01869
01870
01871 gl_light->spot_cutoff = 180.0f;
01872
01873 const LVecBase3 &att = light_obj->get_attenuation();
01874 gl_light->attenuation[0] = att[0];
01875 gl_light->attenuation[1] = att[1];
01876 gl_light->attenuation[2] = att[2];
01877 }
01878
01879 nassertv(gl_light->next == NULL);
01880
01881
01882 gl_light->next = _c->first_light;
01883 _c->first_light = gl_light;
01884 }
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894 void TinyGraphicsStateGuardian::
01895 bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
01896 pair<Lights::iterator, bool> lookup = _dlights.insert(Lights::value_type(light, GLLight()));
01897 GLLight *gl_light = &(*lookup.first).second;
01898 if (lookup.second) {
01899
01900 memset(gl_light, 0, sizeof(GLLight));
01901
01902 const LColor &specular = light_obj->get_specular_color();
01903 gl_light->specular.v[0] = specular[0];
01904 gl_light->specular.v[1] = specular[1];
01905 gl_light->specular.v[2] = specular[2];
01906 gl_light->specular.v[3] = specular[3];
01907
01908
01909
01910 CPT(TransformState) render_transform =
01911 _cs_transform->compose(_scene_setup->get_world_transform());
01912
01913 CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
01914 CPT(TransformState) net_transform = render_transform->compose(transform);
01915
01916 LVector3 dir = light_obj->get_direction() * net_transform->get_mat();
01917 dir.normalize();
01918 gl_light->position.v[0] = -dir[0];
01919 gl_light->position.v[1] = -dir[1];
01920 gl_light->position.v[2] = -dir[2];
01921 gl_light->position.v[3] = 0.0f;
01922
01923 gl_light->norm_position.v[0] = -dir[0];
01924 gl_light->norm_position.v[1] = -dir[1];
01925 gl_light->norm_position.v[2] = -dir[2];
01926 gl_V3_Norm(&gl_light->norm_position);
01927
01928
01929 gl_light->spot_exponent = 0.0f;
01930
01931
01932 gl_light->spot_cutoff = 180.0f;
01933
01934
01935
01936 gl_light->attenuation[0] = 1.0f;
01937 gl_light->attenuation[1] = 0.0f;
01938 gl_light->attenuation[2] = 0.0f;
01939 }
01940
01941 nassertv(gl_light->next == NULL);
01942
01943
01944 gl_light->next = _c->first_light;
01945 _c->first_light = gl_light;
01946 }
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956 void TinyGraphicsStateGuardian::
01957 bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
01958 pair<Lights::iterator, bool> lookup = _plights.insert(Lights::value_type(light, GLLight()));
01959 GLLight *gl_light = &(*lookup.first).second;
01960 if (lookup.second) {
01961
01962 memset(gl_light, 0, sizeof(GLLight));
01963
01964 const LColor &specular = light_obj->get_specular_color();
01965 gl_light->specular.v[0] = specular[0];
01966 gl_light->specular.v[1] = specular[1];
01967 gl_light->specular.v[2] = specular[2];
01968 gl_light->specular.v[3] = specular[3];
01969
01970 Lens *lens = light_obj->get_lens();
01971 nassertv(lens != (Lens *)NULL);
01972
01973
01974
01975 CPT(TransformState) render_transform =
01976 _cs_transform->compose(_scene_setup->get_world_transform());
01977
01978 CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
01979 CPT(TransformState) net_transform = render_transform->compose(transform);
01980
01981 const LMatrix4 &light_mat = net_transform->get_mat();
01982 LPoint3 pos = lens->get_nodal_point() * light_mat;
01983 LVector3 dir = lens->get_view_vector() * light_mat;
01984 dir.normalize();
01985
01986 gl_light->position.v[0] = pos[0];
01987 gl_light->position.v[1] = pos[1];
01988 gl_light->position.v[2] = pos[2];
01989 gl_light->position.v[3] = 1.0f;
01990
01991 gl_light->spot_direction.v[0] = dir[0];
01992 gl_light->spot_direction.v[1] = dir[1];
01993 gl_light->spot_direction.v[2] = dir[2];
01994
01995 gl_light->norm_spot_direction.v[0] = dir[0];
01996 gl_light->norm_spot_direction.v[1] = dir[1];
01997 gl_light->norm_spot_direction.v[2] = dir[2];
01998 gl_V3_Norm(&gl_light->norm_spot_direction);
01999
02000 gl_light->spot_exponent = light_obj->get_exponent();
02001 gl_light->spot_cutoff = lens->get_hfov() * 0.5f;
02002
02003 const LVecBase3 &att = light_obj->get_attenuation();
02004 gl_light->attenuation[0] = att[0];
02005 gl_light->attenuation[1] = att[1];
02006 gl_light->attenuation[2] = att[2];
02007 }
02008
02009 nassertv(gl_light->next == NULL);
02010
02011
02012 gl_light->next = _c->first_light;
02013 _c->first_light = gl_light;
02014 }
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025 void TinyGraphicsStateGuardian::
02026 do_issue_transform() {
02027 _transform_state_pcollector.add_level(1);
02028 _transform_stale = true;
02029
02030 if (_auto_rescale_normal) {
02031 do_auto_rescale_normal();
02032 }
02033 }
02034
02035
02036
02037
02038
02039
02040 void TinyGraphicsStateGuardian::
02041 do_issue_render_mode() {
02042 const RenderModeAttrib *target_render_mode = DCAST(RenderModeAttrib, _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot()));
02043
02044 _filled_flat = false;
02045
02046 switch (target_render_mode->get_mode()) {
02047 case RenderModeAttrib::M_unchanged:
02048 case RenderModeAttrib::M_filled:
02049 _c->draw_triangle_front = gl_draw_triangle_fill;
02050 _c->draw_triangle_back = gl_draw_triangle_fill;
02051 break;
02052
02053 case RenderModeAttrib::M_filled_flat:
02054 _c->draw_triangle_front = gl_draw_triangle_fill;
02055 _c->draw_triangle_back = gl_draw_triangle_fill;
02056 _filled_flat = true;
02057 break;
02058
02059 case RenderModeAttrib::M_wireframe:
02060 _c->draw_triangle_front = gl_draw_triangle_line;
02061 _c->draw_triangle_back = gl_draw_triangle_line;
02062 break;
02063
02064 case RenderModeAttrib::M_point:
02065 _c->draw_triangle_front = gl_draw_triangle_point;
02066 _c->draw_triangle_back = gl_draw_triangle_point;
02067 break;
02068
02069 default:
02070 tinydisplay_cat.error()
02071 << "Unknown render mode " << (int)target_render_mode->get_mode() << endl;
02072 }
02073 }
02074
02075
02076
02077
02078
02079
02080 void TinyGraphicsStateGuardian::
02081 do_issue_rescale_normal() {
02082 const RescaleNormalAttrib *target_rescale_normal = DCAST(RescaleNormalAttrib, _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot()));
02083 RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode();
02084
02085 _auto_rescale_normal = false;
02086
02087 switch (mode) {
02088 case RescaleNormalAttrib::M_none:
02089 _c->normalize_enabled = false;
02090 _c->normal_scale = 1.0f;
02091 break;
02092
02093 case RescaleNormalAttrib::M_normalize:
02094 _c->normalize_enabled = true;
02095 _c->normal_scale = 1.0f;
02096 break;
02097
02098 case RescaleNormalAttrib::M_rescale:
02099 case RescaleNormalAttrib::M_auto:
02100 _auto_rescale_normal = true;
02101 do_auto_rescale_normal();
02102 break;
02103
02104 default:
02105 tinydisplay_cat.error()
02106 << "Unknown rescale_normal mode " << (int)mode << endl;
02107 }
02108 }
02109
02110
02111
02112
02113
02114
02115 void TinyGraphicsStateGuardian::
02116 do_issue_depth_offset() {
02117 const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()));
02118 int offset = target_depth_offset->get_offset();
02119 _c->zbias = offset;
02120 }
02121
02122
02123
02124
02125
02126
02127 void TinyGraphicsStateGuardian::
02128 do_issue_cull_face() {
02129 const CullFaceAttrib *target_cull_face = DCAST(CullFaceAttrib, _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot()));
02130 CullFaceAttrib::Mode mode = target_cull_face->get_effective_mode();
02131
02132 switch (mode) {
02133 case CullFaceAttrib::M_cull_none:
02134 _c->cull_face_enabled = false;
02135 break;
02136 case CullFaceAttrib::M_cull_clockwise:
02137 _c->cull_face_enabled = true;
02138 _c->cull_clockwise = true;
02139 break;
02140 case CullFaceAttrib::M_cull_counter_clockwise:
02141 _c->cull_face_enabled = true;
02142 _c->cull_clockwise = false;
02143 break;
02144 default:
02145 tinydisplay_cat.error()
02146 << "invalid cull face mode " << (int)mode << endl;
02147 break;
02148 }
02149 }
02150
02151
02152
02153
02154
02155
02156 void TinyGraphicsStateGuardian::
02157 do_issue_material() {
02158 static Material empty;
02159
02160 const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()));
02161
02162 const Material *material;
02163 if (target_material == (MaterialAttrib *)NULL ||
02164 target_material->is_off()) {
02165 material = ∅
02166 } else {
02167 material = target_material->get_material();
02168 }
02169
02170
02171 setup_material(&_c->materials[0], material);
02172
02173 if (material->get_twoside()) {
02174
02175 setup_material(&_c->materials[1], material);
02176 }
02177
02178 _c->local_light_model = material->get_local();
02179 _c->light_model_two_side = material->get_twoside();
02180 }
02181
02182
02183
02184
02185
02186
02187 void TinyGraphicsStateGuardian::
02188 do_issue_texture() {
02189 _texturing_state = 0;
02190 _c->num_textures_enabled = 0;
02191
02192 int num_stages = _target_texture->get_num_on_ff_stages();
02193 if (num_stages == 0) {
02194
02195 return;
02196 }
02197 nassertv(num_stages <= MAX_TEXTURE_STAGES);
02198
02199 bool all_replace = true;
02200 bool all_nearest = true;
02201 bool all_mipmap_nearest = true;
02202 bool any_mipmap = false;
02203 bool needs_general = false;
02204 Texture::QualityLevel best_quality_level = Texture::QL_default;
02205
02206 for (int si = 0; si < num_stages; ++si) {
02207 TextureStage *stage = _target_texture->get_on_ff_stage(si);
02208 Texture *texture = _target_texture->get_on_texture(stage);
02209 nassertv(texture != (Texture *)NULL);
02210
02211 int view = get_current_tex_view_offset() + stage->get_tex_view_offset();
02212 TextureContext *tc = texture->prepare_now(view, _prepared_objects, this);
02213 if (tc == (TextureContext *)NULL) {
02214
02215 return;
02216 }
02217
02218
02219 if (!update_texture(tc, false, si)) {
02220 return;
02221 }
02222
02223
02224
02225 if (stage->get_mode() != TextureStage::M_replace) {
02226 all_replace = false;
02227 }
02228
02229 Texture::QualityLevel quality_level = _texture_quality_override;
02230 if (quality_level == Texture::QL_default) {
02231 quality_level = texture->get_quality_level();
02232 }
02233 if (quality_level == Texture::QL_default) {
02234 quality_level = texture_quality_level;
02235 }
02236
02237 best_quality_level = max(best_quality_level, quality_level);
02238
02239 ZTextureDef *texture_def = &_c->zb->current_textures[si];
02240
02241
02242
02243 Texture::FilterType minfilter = texture->get_minfilter();
02244 Texture::FilterType magfilter = texture->get_magfilter();
02245
02246 if (td_ignore_mipmaps && Texture::is_mipmap(minfilter)) {
02247
02248 if (minfilter == Texture::FT_nearest_mipmap_nearest) {
02249 minfilter = Texture::FT_nearest;
02250 } else {
02251 minfilter = Texture::FT_linear;
02252 }
02253 }
02254
02255
02256
02257 if (quality_level == Texture::QL_fastest) {
02258 minfilter = Texture::FT_nearest;
02259 magfilter = Texture::FT_nearest;
02260
02261 } else if (quality_level == Texture::QL_normal) {
02262 if (Texture::is_mipmap(minfilter)) {
02263 minfilter = Texture::FT_nearest_mipmap_nearest;
02264 } else {
02265 minfilter = Texture::FT_nearest;
02266 }
02267 magfilter = Texture::FT_nearest;
02268
02269 } else if (quality_level == Texture::QL_best) {
02270 minfilter = texture->get_effective_minfilter();
02271 magfilter = texture->get_effective_magfilter();
02272 }
02273
02274 texture_def->tex_minfilter_func = get_tex_filter_func(minfilter);
02275 texture_def->tex_magfilter_func = get_tex_filter_func(magfilter);
02276
02277 Texture::WrapMode wrap_u = texture->get_wrap_u();
02278 Texture::WrapMode wrap_v = texture->get_wrap_v();
02279 if (td_ignore_clamp) {
02280 wrap_u = Texture::WM_repeat;
02281 wrap_v = Texture::WM_repeat;
02282 }
02283
02284 if (wrap_u != Texture::WM_repeat || wrap_v != Texture::WM_repeat) {
02285
02286
02287 needs_general = true;
02288
02289
02290
02291
02292
02293
02294 texture_def->tex_minfilter_func_impl = texture_def->tex_minfilter_func;
02295 texture_def->tex_magfilter_func_impl = texture_def->tex_magfilter_func;
02296
02297
02298
02299 texture_def->tex_minfilter_func = apply_wrap_general_minfilter;
02300 texture_def->tex_magfilter_func = apply_wrap_general_magfilter;
02301
02302 texture_def->tex_wrap_u_func = get_tex_wrap_func(wrap_u);
02303 texture_def->tex_wrap_v_func = get_tex_wrap_func(wrap_v);
02304
02305
02306
02307 if (wrap_u && Texture::WM_border_color && wrap_v == Texture::WM_border_color) {
02308 texture_def->tex_minfilter_func = apply_wrap_border_color_minfilter;
02309 texture_def->tex_magfilter_func = apply_wrap_border_color_magfilter;
02310 } else if (wrap_u && Texture::WM_clamp && wrap_v == Texture::WM_clamp) {
02311 texture_def->tex_minfilter_func = apply_wrap_clamp_minfilter;
02312 texture_def->tex_magfilter_func = apply_wrap_clamp_magfilter;
02313 }
02314 }
02315
02316 if (minfilter != Texture::FT_nearest || magfilter != Texture::FT_nearest) {
02317 all_nearest = false;
02318 }
02319
02320 if (minfilter != Texture::FT_nearest_mipmap_nearest ||
02321 magfilter != Texture::FT_nearest) {
02322 all_mipmap_nearest = false;
02323 }
02324
02325 if (Texture::is_mipmap(minfilter)) {
02326 any_mipmap = true;
02327 }
02328 }
02329
02330
02331 _c->num_textures_enabled = num_stages;
02332 _texture_replace = all_replace;
02333
02334 _texturing_state = 2;
02335 if (num_stages >= 3) {
02336 _texturing_state = 4;
02337 } else if (num_stages == 2) {
02338 _texturing_state = 3;
02339 } else if (!td_perspective_textures) {
02340 _texturing_state = 1;
02341 }
02342
02343 if (best_quality_level == Texture::QL_best) {
02344
02345 _texfilter_state = 2;
02346
02347 if (!needs_general) {
02348 if (all_nearest) {
02349
02350 _texfilter_state = 0;
02351 } else if (all_mipmap_nearest) {
02352
02353 _texfilter_state = 1;
02354 }
02355 }
02356
02357 } else if (best_quality_level == Texture::QL_fastest) {
02358
02359
02360 _texfilter_state = 0;
02361 _texturing_state = 1;
02362
02363 } else {
02364
02365
02366
02367 _texfilter_state = 0;
02368 if (any_mipmap) {
02369 _texfilter_state = 1;
02370 }
02371
02372 if (needs_general) {
02373
02374
02375 _texfilter_state = 2;
02376 }
02377 }
02378 }
02379
02380
02381
02382
02383
02384
02385 void TinyGraphicsStateGuardian::
02386 do_issue_scissor() {
02387 const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot()));
02388 const LVecBase4 &frame = target_scissor->get_frame();
02389 set_scissor(frame[0], frame[1], frame[2], frame[3]);
02390 }
02391
02392
02393
02394
02395
02396
02397
02398 void TinyGraphicsStateGuardian::
02399 set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
02400 _c->scissor.left = left;
02401 _c->scissor.right = right;
02402 _c->scissor.bottom = bottom;
02403 _c->scissor.top = top;
02404 gl_eval_viewport(_c);
02405
02406 PN_stdfloat xsize = right - left;
02407 PN_stdfloat ysize = top - bottom;
02408 PN_stdfloat xcenter = (left + right) - 1.0f;
02409 PN_stdfloat ycenter = (bottom + top) - 1.0f;
02410 if (xsize == 0.0f || ysize == 0.0f) {
02411
02412
02413 _scissor_mat = TransformState::make_identity();
02414 } else {
02415 _scissor_mat = TransformState::make_scale(LVecBase3(1.0f / xsize, 1.0f / ysize, 1.0f))->compose(TransformState::make_pos(LPoint3(-xcenter, -ycenter, 0.0f)));
02416 }
02417 }
02418
02419
02420
02421
02422
02423
02424
02425
02426 bool TinyGraphicsStateGuardian::
02427 apply_texture(TextureContext *tc) {
02428 TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
02429
02430 gtc->set_active(true);
02431 return true;
02432 }
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442 bool TinyGraphicsStateGuardian::
02443 upload_texture(TinyTextureContext *gtc, bool force) {
02444 Texture *tex = gtc->get_texture();
02445
02446 if (_effective_incomplete_render && !force) {
02447 if (!tex->has_ram_image() && tex->might_have_ram_image() &&
02448 tex->has_simple_ram_image() &&
02449 !_loader.is_null()) {
02450
02451
02452 async_reload_texture(gtc);
02453 if (!tex->has_ram_image()) {
02454 if (gtc->was_simple_image_modified()) {
02455 return upload_simple_texture(gtc);
02456 }
02457 return true;
02458 }
02459 }
02460 }
02461
02462 PStatTimer timer(_load_texture_pcollector);
02463 CPTA_uchar src_image = tex->get_uncompressed_ram_image();
02464 if (src_image.is_null()) {
02465 return false;
02466 }
02467
02468 if (tinydisplay_cat.is_debug()) {
02469 tinydisplay_cat.debug()
02470 << "loading texture " << tex->get_name() << "\n";
02471 }
02472 #ifdef DO_PSTATS
02473 _data_transferred_pcollector.add_level(tex->get_ram_image_size());
02474 #endif
02475 GLTexture *gltex = >c->_gltex;
02476
02477 int num_levels = 1;
02478 if (tex->uses_mipmaps()) {
02479 if (!tex->has_all_ram_mipmap_images()) {
02480 tex->generate_ram_mipmap_images();
02481 }
02482 num_levels = tex->get_num_ram_mipmap_images();
02483 }
02484
02485 if (!setup_gltex(gltex, tex->get_x_size(), tex->get_y_size(), num_levels)) {
02486 return false;
02487 }
02488 LColor border_color = tex->get_border_color();
02489 gltex->border_color.v[0] = border_color[0];
02490 gltex->border_color.v[1] = border_color[1];
02491 gltex->border_color.v[2] = border_color[2];
02492 gltex->border_color.v[3] = border_color[3];
02493
02494 int bytecount = 0;
02495 int xsize = gltex->xsize;
02496 int ysize = gltex->ysize;
02497
02498 for (int level = 0; level < gltex->num_levels; ++level) {
02499 ZTextureLevel *dest = &gltex->levels[level];
02500
02501 switch (tex->get_format()) {
02502 case Texture::F_rgb:
02503 case Texture::F_rgb5:
02504 case Texture::F_rgb8:
02505 case Texture::F_rgb12:
02506 case Texture::F_rgb332:
02507 copy_rgb_image(dest, xsize, ysize, gtc, level);
02508 break;
02509
02510 case Texture::F_rgba:
02511 case Texture::F_rgbm:
02512 case Texture::F_rgba4:
02513 case Texture::F_rgba5:
02514 case Texture::F_rgba8:
02515 case Texture::F_rgba12:
02516 case Texture::F_rgba16:
02517 case Texture::F_rgba32:
02518 copy_rgba_image(dest, xsize, ysize, gtc, level);
02519 break;
02520
02521 case Texture::F_luminance:
02522 copy_lum_image(dest, xsize, ysize, gtc, level);
02523 break;
02524
02525 case Texture::F_red:
02526 copy_one_channel_image(dest, xsize, ysize, gtc, level, 0);
02527 break;
02528
02529 case Texture::F_green:
02530 copy_one_channel_image(dest, xsize, ysize, gtc, level, 1);
02531 break;
02532
02533 case Texture::F_blue:
02534 copy_one_channel_image(dest, xsize, ysize, gtc, level, 2);
02535 break;
02536
02537 case Texture::F_alpha:
02538 copy_alpha_image(dest, xsize, ysize, gtc, level);
02539 break;
02540
02541 case Texture::F_luminance_alphamask:
02542 case Texture::F_luminance_alpha:
02543 copy_la_image(dest, xsize, ysize, gtc, level);
02544 break;
02545 }
02546
02547 bytecount += xsize * ysize * 4;
02548 xsize = max(xsize >> 1, 1);
02549 ysize = max(ysize >> 1, 1);
02550 }
02551
02552 gtc->update_data_size_bytes(bytecount);
02553
02554 get_engine()->texture_uploaded(tex);
02555 gtc->mark_loaded();
02556
02557 return true;
02558 }
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570 bool TinyGraphicsStateGuardian::
02571 upload_simple_texture(TinyTextureContext *gtc) {
02572 PStatTimer timer(_load_texture_pcollector);
02573 Texture *tex = gtc->get_texture();
02574 nassertr(tex != (Texture *)NULL, false);
02575
02576 const unsigned char *image_ptr = tex->get_simple_ram_image();
02577 if (image_ptr == (const unsigned char *)NULL) {
02578 return false;
02579 }
02580
02581 size_t image_size = tex->get_simple_ram_image_size();
02582 int width = tex->get_simple_x_size();
02583 int height = tex->get_simple_y_size();
02584
02585 #ifdef DO_PSTATS
02586 _data_transferred_pcollector.add_level(image_size);
02587 #endif
02588 GLTexture *gltex = >c->_gltex;
02589
02590 if (tinydisplay_cat.is_debug()) {
02591 tinydisplay_cat.debug()
02592 << "loading simple image for " << tex->get_name() << "\n";
02593 }
02594
02595 if (!setup_gltex(gltex, width, height, 1)) {
02596 return false;
02597 }
02598 LColor border_color = tex->get_border_color();
02599 gltex->border_color.v[0] = border_color[0];
02600 gltex->border_color.v[1] = border_color[1];
02601 gltex->border_color.v[2] = border_color[2];
02602 gltex->border_color.v[3] = border_color[3];
02603
02604 ZTextureLevel *dest = &gltex->levels[0];
02605 memcpy(dest->pixmap, image_ptr, image_size);
02606
02607 gtc->mark_simple_loaded();
02608
02609 return true;
02610 }
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620 bool TinyGraphicsStateGuardian::
02621 setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
02622 int s_bits = get_tex_shift(x_size);
02623 int t_bits = get_tex_shift(y_size);
02624
02625 if (s_bits < 0 || t_bits < 0) {
02626 return false;
02627 }
02628
02629 num_levels = min(num_levels, MAX_MIPMAP_LEVELS);
02630
02631 gltex->xsize = x_size;
02632 gltex->ysize = y_size;
02633
02634 gltex->s_max = 1 << (s_bits + ZB_POINT_ST_FRAC_BITS);
02635 gltex->t_max = 1 << (t_bits + ZB_POINT_ST_FRAC_BITS);
02636
02637 gltex->num_levels = num_levels;
02638
02639
02640
02641
02642
02643 int total_bytecount = 0;
02644
02645
02646 {
02647 int x = x_size;
02648 int y = y_size;
02649 for (int level = 0; level < num_levels; ++level) {
02650 int bytecount = x * y * 4;
02651 total_bytecount += bytecount;
02652 x = max((x >> 1), 1);
02653 y = max((y >> 1), 1);
02654 }
02655 }
02656
02657 if (gltex->total_bytecount != total_bytecount) {
02658 if (gltex->allocated_buffer != NULL) {
02659 PANDA_FREE_ARRAY(gltex->allocated_buffer);
02660 TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
02661 }
02662 gltex->allocated_buffer = PANDA_MALLOC_ARRAY(total_bytecount);
02663 gltex->total_bytecount = total_bytecount;
02664 TinyTextureContext::get_class_type().inc_memory_usage(TypeHandle::MC_array, total_bytecount);
02665 }
02666
02667 char *next_buffer = (char *)gltex->allocated_buffer;
02668 char *end_of_buffer = next_buffer + total_bytecount;
02669
02670 int level = 0;
02671 ZTextureLevel *dest = NULL;
02672 while (level < num_levels) {
02673 dest = &gltex->levels[level];
02674 int bytecount = x_size * y_size * 4;
02675 dest->pixmap = (PIXEL *)next_buffer;
02676 next_buffer += bytecount;
02677 nassertr(next_buffer <= end_of_buffer, false);
02678
02679 dest->s_mask = ((1 << (s_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
02680 dest->t_mask = ((1 << (t_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
02681 dest->s_shift = (ZB_POINT_ST_FRAC_BITS + level);
02682 dest->t_shift = (ZB_POINT_ST_FRAC_BITS - s_bits + level);
02683
02684 x_size = max((x_size >> 1), 1);
02685 y_size = max((y_size >> 1), 1);
02686 s_bits = max(s_bits - 1, 0);
02687 t_bits = max(t_bits - 1, 0);
02688
02689 ++level;
02690 }
02691
02692
02693
02694
02695 while (level < MAX_MIPMAP_LEVELS) {
02696 gltex->levels[level] = *dest;
02697 ++level;
02698 }
02699
02700 return true;
02701 }
02702
02703
02704
02705
02706
02707
02708
02709
02710 int TinyGraphicsStateGuardian::
02711 get_tex_shift(int orig_size) {
02712 if ((orig_size & (orig_size - 1)) != 0) {
02713
02714 return -1;
02715 }
02716 if (orig_size > _max_texture_dimension) {
02717 return -1;
02718 }
02719
02720 return count_bits_in_word((unsigned int)orig_size - 1);
02721 }
02722
02723
02724
02725
02726
02727
02728
02729 void TinyGraphicsStateGuardian::
02730 copy_lum_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
02731 Texture *tex = gtc->get_texture();
02732 nassertv(tex->get_num_components() == 1);
02733 nassertv(tex->get_expected_mipmap_x_size(level) == xsize &&
02734 tex->get_expected_mipmap_y_size(level) == ysize);
02735
02736 CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
02737 nassertv(!src_image.is_null());
02738 const unsigned char *src = src_image.p();
02739 size_t view_size = tex->get_ram_mipmap_view_size(level);
02740 src += view_size * gtc->get_view();
02741
02742
02743 int cw = tex->get_component_width();
02744 #ifdef WORDS_BIGENDIAN
02745
02746 static const int co = 0;
02747 #else
02748
02749 int co = cw - 1;
02750 #endif
02751
02752 unsigned int *dpix = (unsigned int *)dest->pixmap;
02753 nassertv(dpix != NULL);
02754 const unsigned char *spix = src;
02755 int pixel_count = xsize * ysize;
02756 while (pixel_count-- > 0) {
02757 *dpix = RGBA8_TO_PIXEL(spix[co], spix[co], spix[co], 0xff);
02758 ++dpix;
02759 spix += cw;
02760 }
02761 }
02762
02763
02764
02765
02766
02767
02768
02769 void TinyGraphicsStateGuardian::
02770 copy_alpha_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
02771 Texture *tex = gtc->get_texture();
02772 nassertv(tex->get_num_components() == 1);
02773
02774 CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
02775 nassertv(!src_image.is_null());
02776 const unsigned char *src = src_image.p();
02777 size_t view_size = tex->get_ram_mipmap_view_size(level);
02778 src += view_size * gtc->get_view();
02779
02780
02781 int cw = tex->get_component_width();
02782 #ifdef WORDS_BIGENDIAN
02783
02784 static const int co = 0;
02785 #else
02786
02787 int co = cw - 1;
02788 #endif
02789
02790 unsigned int *dpix = (unsigned int *)dest->pixmap;
02791 nassertv(dpix != NULL);
02792 const unsigned char *spix = src;
02793 int pixel_count = xsize * ysize;
02794 while (pixel_count-- > 0) {
02795 *dpix = RGBA8_TO_PIXEL(0xff, 0xff, 0xff, spix[co]);
02796 ++dpix;
02797 spix += cw;
02798 }
02799 }
02800
02801
02802
02803
02804
02805
02806
02807
02808 void TinyGraphicsStateGuardian::
02809 copy_one_channel_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level, int channel) {
02810 Texture *tex = gtc->get_texture();
02811 nassertv(tex->get_num_components() == 1);
02812
02813 CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
02814 nassertv(!src_image.is_null());
02815 const unsigned char *src = src_image.p();
02816 size_t view_size = tex->get_ram_mipmap_view_size(level);
02817 src += view_size * gtc->get_view();
02818
02819
02820 int cw = tex->get_component_width();
02821 #ifdef WORDS_BIGENDIAN
02822
02823 static const int co = 0;
02824 #else
02825
02826 int co = cw - 1;
02827 #endif
02828
02829 unsigned int *dpix = (unsigned int *)dest->pixmap;
02830 nassertv(dpix != NULL);
02831 const unsigned char *spix = src;
02832 int pixel_count = xsize * ysize;
02833
02834 switch (channel) {
02835 case 0:
02836 while (pixel_count-- > 0) {
02837 *dpix = RGBA8_TO_PIXEL(spix[co], 0, 0, 0xff);
02838 ++dpix;
02839 spix += cw;
02840 }
02841 break;
02842
02843 case 1:
02844 while (pixel_count-- > 0) {
02845 *dpix = RGBA8_TO_PIXEL(0, spix[co], 0, 0xff);
02846 ++dpix;
02847 spix += cw;
02848 }
02849 break;
02850
02851 case 2:
02852 while (pixel_count-- > 0) {
02853 *dpix = RGBA8_TO_PIXEL(0, 0, spix[co], 0xff);
02854 ++dpix;
02855 spix += cw;
02856 }
02857 break;
02858
02859 case 3:
02860 while (pixel_count-- > 0) {
02861 *dpix = RGBA8_TO_PIXEL(0, 0, 0, spix[co]);
02862 ++dpix;
02863 spix += cw;
02864 }
02865 break;
02866 }
02867 }
02868
02869
02870
02871
02872
02873
02874
02875
02876 void TinyGraphicsStateGuardian::
02877 copy_la_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
02878 Texture *tex = gtc->get_texture();
02879 nassertv(tex->get_num_components() == 2);
02880
02881 CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
02882 nassertv(!src_image.is_null());
02883 const unsigned char *src = src_image.p();
02884 size_t view_size = tex->get_ram_mipmap_view_size(level);
02885 src += view_size * gtc->get_view();
02886
02887
02888 int cw = tex->get_component_width();
02889 #ifdef WORDS_BIGENDIAN
02890
02891 static const int co = 0;
02892 #else
02893
02894 int co = cw - 1;
02895 #endif
02896
02897 unsigned int *dpix = (unsigned int *)dest->pixmap;
02898 nassertv(dpix != NULL);
02899 const unsigned char *spix = src;
02900 int pixel_count = xsize * ysize;
02901 int inc = 2 * cw;
02902 while (pixel_count-- > 0) {
02903 *dpix = RGBA8_TO_PIXEL(spix[co], spix[co], spix[co], spix[cw + co]);
02904 ++dpix;
02905 spix += inc;
02906 }
02907 }
02908
02909
02910
02911
02912
02913
02914
02915 void TinyGraphicsStateGuardian::
02916 copy_rgb_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
02917 Texture *tex = gtc->get_texture();
02918 nassertv(tex->get_num_components() == 3);
02919
02920 CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
02921 nassertv(!src_image.is_null());
02922 const unsigned char *src = src_image.p();
02923 size_t view_size = tex->get_ram_mipmap_view_size(level);
02924 src += view_size * gtc->get_view();
02925
02926
02927 int cw = tex->get_component_width();
02928 #ifdef WORDS_BIGENDIAN
02929
02930 static const int co = 0;
02931 #else
02932
02933 int co = cw - 1;
02934 #endif
02935
02936 unsigned int *dpix = (unsigned int *)dest->pixmap;
02937 nassertv(dpix != NULL);
02938 const unsigned char *spix = src;
02939 int pixel_count = xsize * ysize;
02940 int inc = 3 * cw;
02941 while (pixel_count-- > 0) {
02942 *dpix = RGBA8_TO_PIXEL(spix[cw + cw + co], spix[cw + co], spix[co], 0xff);
02943 ++dpix;
02944 spix += inc;
02945 }
02946 }
02947
02948
02949
02950
02951
02952
02953
02954 void TinyGraphicsStateGuardian::
02955 copy_rgba_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
02956 Texture *tex = gtc->get_texture();
02957 nassertv(tex->get_num_components() == 4);
02958
02959 CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
02960 nassertv(!src_image.is_null());
02961 const unsigned char *src = src_image.p();
02962 size_t view_size = tex->get_ram_mipmap_view_size(level);
02963 src += view_size * gtc->get_view();
02964
02965
02966 int cw = tex->get_component_width();
02967 #ifdef WORDS_BIGENDIAN
02968
02969 static const int co = 0;
02970 #else
02971
02972 int co = cw - 1;
02973 #endif
02974
02975 unsigned int *dpix = (unsigned int *)dest->pixmap;
02976 nassertv(dpix != NULL);
02977 const unsigned char *spix = src;
02978 int pixel_count = xsize * ysize;
02979 int inc = 4 * cw;
02980 while (pixel_count-- > 0) {
02981 *dpix = RGBA8_TO_PIXEL(spix[cw + cw + co], spix[cw + co], spix[co], spix[cw + cw + cw + co]);
02982 ++dpix;
02983 spix += inc;
02984 }
02985 }
02986
02987
02988
02989
02990
02991
02992
02993 void TinyGraphicsStateGuardian::
02994 setup_material(GLMaterial *gl_material, const Material *material) {
02995 const LColor &specular = material->get_specular();
02996 gl_material->specular.v[0] = specular[0];
02997 gl_material->specular.v[1] = specular[1];
02998 gl_material->specular.v[2] = specular[2];
02999 gl_material->specular.v[3] = specular[3];
03000
03001 const LColor &emission = material->get_emission();
03002 gl_material->emission.v[0] = emission[0];
03003 gl_material->emission.v[1] = emission[1];
03004 gl_material->emission.v[2] = emission[2];
03005 gl_material->emission.v[3] = emission[3];
03006
03007 gl_material->shininess = material->get_shininess();
03008 gl_material->shininess_i = (int)((material->get_shininess() / 128.0f) * SPECULAR_BUFFER_RESOLUTION);
03009
03010 _color_material_flags = CMF_ambient | CMF_diffuse;
03011
03012 if (material->has_ambient()) {
03013 const LColor &ambient = material->get_ambient();
03014 gl_material->ambient.v[0] = ambient[0];
03015 gl_material->ambient.v[1] = ambient[1];
03016 gl_material->ambient.v[2] = ambient[2];
03017 gl_material->ambient.v[3] = ambient[3];
03018
03019 _color_material_flags &= ~CMF_ambient;
03020 }
03021
03022 if (material->has_diffuse()) {
03023 const LColor &diffuse = material->get_diffuse();
03024 gl_material->diffuse.v[0] = diffuse[0];
03025 gl_material->diffuse.v[1] = diffuse[1];
03026 gl_material->diffuse.v[2] = diffuse[2];
03027 gl_material->diffuse.v[3] = diffuse[3];
03028
03029 _color_material_flags &= ~CMF_diffuse;
03030 }
03031 }
03032
03033
03034
03035
03036
03037
03038
03039 void TinyGraphicsStateGuardian::
03040 do_auto_rescale_normal() {
03041 if (_internal_transform->has_uniform_scale()) {
03042
03043 _c->normalize_enabled = false;
03044 _c->normal_scale = _internal_transform->get_uniform_scale();
03045
03046 } else {
03047
03048 _c->normalize_enabled = true;
03049 _c->normal_scale = 1.0f;
03050 }
03051 }
03052
03053
03054
03055
03056
03057
03058
03059
03060 void TinyGraphicsStateGuardian::
03061 load_matrix(M4 *matrix, const TransformState *transform) {
03062 const LMatrix4 &pm = transform->get_mat();
03063 for (int i = 0; i < 4; ++i) {
03064 matrix->m[0][i] = pm.get_cell(i, 0);
03065 matrix->m[1][i] = pm.get_cell(i, 1);
03066 matrix->m[2][i] = pm.get_cell(i, 2);
03067 matrix->m[3][i] = pm.get_cell(i, 3);
03068 }
03069 }
03070
03071
03072
03073
03074
03075
03076
03077
03078 int TinyGraphicsStateGuardian::
03079 get_color_blend_op(ColorBlendAttrib::Operand operand) {
03080 switch (operand) {
03081 case ColorBlendAttrib::O_zero:
03082 return 0;
03083 case ColorBlendAttrib::O_one:
03084 return 1;
03085 case ColorBlendAttrib::O_incoming_color:
03086 return 2;
03087 case ColorBlendAttrib::O_one_minus_incoming_color:
03088 return 3;
03089 case ColorBlendAttrib::O_fbuffer_color:
03090 return 4;
03091 case ColorBlendAttrib::O_one_minus_fbuffer_color:
03092 return 5;
03093 case ColorBlendAttrib::O_incoming_alpha:
03094 return 6;
03095 case ColorBlendAttrib::O_one_minus_incoming_alpha:
03096 return 7;
03097 case ColorBlendAttrib::O_fbuffer_alpha:
03098 return 8;
03099 case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
03100 return 9;
03101 case ColorBlendAttrib::O_constant_color:
03102 return 10;
03103 case ColorBlendAttrib::O_one_minus_constant_color:
03104 return 11;
03105 case ColorBlendAttrib::O_constant_alpha:
03106 return 12;
03107 case ColorBlendAttrib::O_one_minus_constant_alpha:
03108 return 13;
03109
03110 case ColorBlendAttrib::O_incoming_color_saturate:
03111 return 1;
03112
03113 case ColorBlendAttrib::O_color_scale:
03114 return 10;
03115 case ColorBlendAttrib::O_one_minus_color_scale:
03116 return 11;
03117 case ColorBlendAttrib::O_alpha_scale:
03118 return 12;
03119 case ColorBlendAttrib::O_one_minus_alpha_scale:
03120 return 13;
03121 }
03122 return 0;
03123 }
03124
03125
03126
03127
03128
03129
03130
03131 ZB_lookupTextureFunc TinyGraphicsStateGuardian::
03132 get_tex_filter_func(Texture::FilterType filter) {
03133 switch (filter) {
03134 case Texture::FT_nearest:
03135 return &lookup_texture_nearest;
03136
03137 case Texture::FT_linear:
03138 return &lookup_texture_bilinear;
03139
03140 case Texture::FT_nearest_mipmap_nearest:
03141 return &lookup_texture_mipmap_nearest;
03142
03143 case Texture::FT_nearest_mipmap_linear:
03144 return &lookup_texture_mipmap_linear;
03145
03146 case Texture::FT_linear_mipmap_nearest:
03147 return &lookup_texture_mipmap_bilinear;
03148
03149 case Texture::FT_linear_mipmap_linear:
03150 return &lookup_texture_mipmap_trilinear;
03151
03152 default:
03153 return &lookup_texture_nearest;
03154 }
03155 }
03156
03157
03158
03159
03160
03161
03162
03163 ZB_texWrapFunc TinyGraphicsStateGuardian::
03164 get_tex_wrap_func(Texture::WrapMode wrap_mode) {
03165 switch (wrap_mode) {
03166 case Texture::WM_clamp:
03167 case Texture::WM_border_color:
03168 return &texcoord_clamp;
03169
03170 case Texture::WM_repeat:
03171 case Texture::WM_invalid:
03172 return &texcoord_repeat;
03173
03174 case Texture::WM_mirror:
03175 return &texcoord_mirror;
03176
03177 case Texture::WM_mirror_once:
03178 return &texcoord_mirror_once;
03179 }
03180
03181 return &texcoord_repeat;
03182 }
03183
03184
03185
03186
03187
03188
03189
03190 void TinyGraphicsStateGuardian::
03191 texgen_null(V2 &result, TinyGraphicsStateGuardian::TexCoordData &) {
03192 result.v[0] = 0.0;
03193 result.v[1] = 0.0;
03194 }
03195
03196
03197
03198
03199
03200
03201
03202 void TinyGraphicsStateGuardian::
03203 texgen_simple(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
03204
03205 const LVecBase2 &d = tcdata._r1.get_data2();
03206 result.v[0] = d[0];
03207 result.v[1] = d[1];
03208 }
03209
03210
03211
03212
03213
03214
03215
03216 void TinyGraphicsStateGuardian::
03217 texgen_texmat(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
03218
03219 LVecBase4 d = tcdata._r1.get_data4() * tcdata._mat;
03220 result.v[0] = d[0] / d[3];
03221 result.v[1] = d[1] / d[3];
03222 }
03223
03224
03225
03226
03227
03228
03229
03230 void TinyGraphicsStateGuardian::
03231 texgen_sphere_map(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
03232
03233 LVector3 n = tcdata._mat.xform_vec(tcdata._r1.get_data3());
03234 LVector3 u = tcdata._mat.xform_point(tcdata._r2.get_data3());
03235
03236
03237 n.normalize();
03238 u.normalize();
03239
03240
03241 LVector3 r = u - n * dot(n, u) * 2.0f;
03242
03243
03244 PN_stdfloat m = 2.0f * csqrt(r[0] * r[0] + r[1] * r[1] + (r[2] + 1.0f) * (r[2] + 1.0f));
03245
03246
03247 result.v[0] = r[0] / m + 0.5f;
03248 result.v[1] = r[1] / m + 0.5f;
03249
03250
03251
03252
03253
03254
03255
03256 }