From d48ff75151337d70aa48cd359b519d386923caa7 Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 3 May 2008 00:09:36 +0000 Subject: [PATCH] progress on rendering modes --- panda/src/tinydisplay/Sources.pp | 2 +- panda/src/tinydisplay/clip.c | 18 +- panda/src/tinydisplay/image_util.c | 23 +- panda/src/tinydisplay/texture.c | 16 - .../tinydisplay/tinyGraphicsStateGuardian.cxx | 709 +++++++++++++----- .../tinydisplay/tinyGraphicsStateGuardian.h | 9 +- panda/src/tinydisplay/tinyGraphicsWindow.cxx | 4 +- panda/src/tinydisplay/tinyTextureContext.I | 12 +- panda/src/tinydisplay/tinyTextureContext.h | 7 +- panda/src/tinydisplay/zbuffer.c | 237 ------ panda/src/tinydisplay/zbuffer.h | 136 ++-- panda/src/tinydisplay/zfeatures.h | 29 +- panda/src/tinydisplay/zgl.h | 1 + panda/src/tinydisplay/zline.c | 6 - panda/src/tinydisplay/zline.h | 15 +- panda/src/tinydisplay/ztriangle.c | 315 +------- panda/src/tinydisplay/ztriangle.h | 14 +- panda/src/tinydisplay/ztriangle_two.h | 508 +++++++++++++ 18 files changed, 1190 insertions(+), 871 deletions(-) create mode 100644 panda/src/tinydisplay/ztriangle_two.h diff --git a/panda/src/tinydisplay/Sources.pp b/panda/src/tinydisplay/Sources.pp index d798b4455c..cc01e6b7fa 100644 --- a/panda/src/tinydisplay/Sources.pp +++ b/panda/src/tinydisplay/Sources.pp @@ -27,7 +27,7 @@ opinfo.h oscontext.c oscontext.h select.c specbuf.c \ specbuf.h texture.c tinygl.h tinyglu.h vertex.c \ zbuffer.c zbuffer.h zdither.c zfeatures.h zgl.h zline.c \ - zline.h zmath.c zmath.h ztriangle.c ztriangle.h + zline.h zmath.c zmath.h ztriangle.c ztriangle.h ztriangle_two.h #end lib_target diff --git a/panda/src/tinydisplay/clip.c b/panda/src/tinydisplay/clip.c index 3e702a5bfd..9a089a81c1 100644 --- a/panda/src/tinydisplay/clip.c +++ b/panda/src/tinydisplay/clip.c @@ -29,6 +29,8 @@ void gl_transform_to_viewport(GLContext *c,GLVertex *v) + ZB_POINT_GREEN_MIN); v->zp.b=(int)(v->color.v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) + ZB_POINT_BLUE_MIN); + v->zp.a=(int)(v->color.v[3] * (ZB_POINT_ALPHA_MAX - ZB_POINT_ALPHA_MIN) + + ZB_POINT_ALPHA_MIN); /* texture */ @@ -78,6 +80,7 @@ static inline void interpolate(GLVertex *q,GLVertex *p0,GLVertex *p1,float t) q->color.v[0]=p0->color.v[0] + (p1->color.v[0]-p0->color.v[0])*t; q->color.v[1]=p0->color.v[1] + (p1->color.v[1]-p0->color.v[1])*t; q->color.v[2]=p0->color.v[2] + (p1->color.v[2]-p0->color.v[2])*t; + q->color.v[3]=p0->color.v[3] + (p1->color.v[3]-p0->color.v[3])*t; } /* @@ -212,10 +215,12 @@ static inline void updateTmp(GLContext *c, q->color.v[0]=p0->color.v[0] + (p1->color.v[0]-p0->color.v[0])*t; q->color.v[1]=p0->color.v[1] + (p1->color.v[1]-p0->color.v[1])*t; q->color.v[2]=p0->color.v[2] + (p1->color.v[2]-p0->color.v[2])*t; + q->color.v[3]=p0->color.v[3] + (p1->color.v[3]-p0->color.v[3])*t; } else { q->color.v[0]=p0->color.v[0]; q->color.v[1]=p0->color.v[1]; q->color.v[2]=p0->color.v[2]; + q->color.v[3]=p0->color.v[3]; } if (c->texture_2d_enabled) { @@ -393,18 +398,13 @@ void gl_draw_triangle_fill(GLContext *c, } #endif - if (c->texture_2d_enabled) { #ifdef PROFILE + if (c->texture_2d_enabled) { count_triangles_textured++; -#endif - ZB_setTexture(c->zb,c->current_texture->images[0].pixmap); - //ZB_fillTriangleMappingPerspective(c->zb,&p0->zp,&p1->zp,&p2->zp); - ZB_fillTriangleMappingSmooth(c->zb,&p0->zp,&p1->zp,&p2->zp); - } else if (c->current_shade_model == GL_SMOOTH) { - ZB_fillTriangleSmooth(c->zb,&p0->zp,&p1->zp,&p2->zp); - } else { - ZB_fillTriangleFlat(c->zb,&p0->zp,&p1->zp,&p2->zp); } +#endif + + (*c->zb_fill_tri)(c->zb,&p0->zp,&p1->zp,&p2->zp); } /* Render a clipped triangle in line mode */ diff --git a/panda/src/tinydisplay/image_util.c b/panda/src/tinydisplay/image_util.c index bab1226eaf..e62529dd26 100644 --- a/panda/src/tinydisplay/image_util.c +++ b/panda/src/tinydisplay/image_util.c @@ -92,24 +92,24 @@ void gl_resizeImage(unsigned char *dest,int xsize_dest,int ysize_dest, yf=(int) ((y1 - floor(y1)) * INTERP_NORM); if ((xf+yf) <= INTERP_NORM) { - for(j=0;j<3;j++) { - pix[j]=interpolate(pix_src[(yi*xsize_src+xi)*3+j], - pix_src[(yi*xsize_src+xi+1)*3+j], - pix_src[((yi+1)*xsize_src+xi)*3+j], + for(j=0;j<4;j++) { + pix[j]=interpolate(pix_src[(yi*xsize_src+xi)*4+j], + pix_src[(yi*xsize_src+xi+1)*4+j], + pix_src[((yi+1)*xsize_src+xi)*4+j], xf,yf); } } else { xf=INTERP_NORM - xf; yf=INTERP_NORM - yf; - for(j=0;j<3;j++) { - pix[j]=interpolate(pix_src[((yi+1)*xsize_src+xi+1)*3+j], - pix_src[((yi+1)*xsize_src+xi)*3+j], - pix_src[(yi*xsize_src+xi+1)*3+j], + for(j=0;j<4;j++) { + pix[j]=interpolate(pix_src[((yi+1)*xsize_src+xi+1)*4+j], + pix_src[((yi+1)*xsize_src+xi)*4+j], + pix_src[(yi*xsize_src+xi+1)*4+j], xf,yf); } } - pix+=3; + pix+=4; x1+=x1inc; } y1+=y1inc; @@ -139,13 +139,14 @@ void gl_resizeImageNoInterpolate(unsigned char *dest,int xsize_dest,int ysize_de for(x=0;x> FRAC_BITS; yi=y1 >> FRAC_BITS; - pix1=pix_src+(yi*xsize_src+xi)*3; + pix1=pix_src+(yi*xsize_src+xi)*4; pix[0]=pix1[0]; pix[1]=pix1[1]; pix[2]=pix1[2]; + pix[3]=pix1[3]; - pix+=3; + pix+=4; x1+=x1inc; } y1+=y1inc; diff --git a/panda/src/tinydisplay/texture.c b/panda/src/tinydisplay/texture.c index 763ccef605..4b1c57a442 100644 --- a/panda/src/tinydisplay/texture.c +++ b/panda/src/tinydisplay/texture.c @@ -151,12 +151,10 @@ void glopTexImage2D(GLContext *c,GLParam *p) pixels1=pixels; } -#if TGL_FEATURE_RENDER_BITS == 32 } else if ((target == GL_TEXTURE_2D && level == 0 && components == 4 && border == 0 && format == GL_RGBA && type == GL_UNSIGNED_BYTE && width == 256 && height == 256)) { // RGBA format is acceptable if we have 32 render bits. -#endif } else { gl_fatal_error("glTexImage2D: combinaison of parameters not handled"); @@ -166,12 +164,6 @@ void glopTexImage2D(GLContext *c,GLParam *p) im->xsize=width; im->ysize=height; if (im->pixmap!=NULL) gl_free(im->pixmap); -#if TGL_FEATURE_RENDER_BITS == 24 - im->pixmap=gl_malloc(width*height*3); - if(im->pixmap) { - memcpy(im->pixmap,pixels1,width*height*3); - } -#elif TGL_FEATURE_RENDER_BITS == 32 im->pixmap=gl_malloc(width*height*4); if(im->pixmap) { if (components == 4) { @@ -180,14 +172,6 @@ void glopTexImage2D(GLContext *c,GLParam *p) gl_convertRGB_to_8A8R8G8B(im->pixmap,pixels1,width,height); } } -#elif TGL_FEATURE_RENDER_BITS == 16 - im->pixmap=gl_malloc(width*height*2); - if(im->pixmap) { - gl_convertRGB_to_5R6G5B(im->pixmap,pixels1,width,height); - } -#else -#error TODO -#endif if (do_free) gl_free(pixels1); } diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index c931799b99..c5380d20cb 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx @@ -31,139 +31,61 @@ TypeHandle TinyGraphicsStateGuardian::_type_handle; PStatCollector TinyGraphicsStateGuardian::_vertices_immediate_pcollector("Vertices:Immediate mode"); -//////////////////////////////////////////////////////////////////// -// Function: uchar_bgr_to_rgb -// Description: Recopies the given array of pixels, converting from -// BGR to RGB arrangement. -//////////////////////////////////////////////////////////////////// -static void -uchar_bgr_to_rgb(unsigned char *dest, const unsigned char *source, - int num_pixels) { - for (int i = 0; i < num_pixels; i++) { - dest[0] = source[2]; - dest[1] = source[1]; - dest[2] = source[0]; - dest += 3; - source += 3; - } -} -/* -//////////////////////////////////////////////////////////////////// -// Function: uchar_bgra_to_rgba -// Description: Recopies the given array of pixels, converting from -// BGRA to RGBA arrangement. -//////////////////////////////////////////////////////////////////// -static void -uchar_bgra_to_rgba(unsigned char *dest, const unsigned char *source, - int num_pixels) { - for (int i = 0; i < num_pixels; i++) { - dest[0] = source[2]; - dest[1] = source[1]; - dest[2] = source[0]; - dest[3] = source[3]; - dest += 4; - source += 4; - } -} -*/ - -//////////////////////////////////////////////////////////////////// -// Function: uchar_bgra_to_rgb -// Description: Recopies the given array of pixels, converting from -// BGRA to RGB arrangement, dropping alpha. -//////////////////////////////////////////////////////////////////// -static void -uchar_bgra_to_rgb(unsigned char *dest, const unsigned char *source, - int num_pixels) { - for (int i = 0; i < num_pixels; i++) { - dest[0] = source[2] * source[3] / 255; - dest[1] = source[1] * source[3] / 255; - dest[2] = source[0] * source[3] / 255; - dest += 3; - source += 4; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: uchar_lum_to_rgb -// Description: Recopies the given array of pixels, converting from -// luminance to RGB arrangement. -//////////////////////////////////////////////////////////////////// -static void -uchar_lum_to_rgb(unsigned char *dest, const unsigned char *source, - int num_pixels) { - for (int i = 0; i < num_pixels; i++) { - dest[0] = source[0]; - dest[1] = source[0]; - dest[2] = source[0]; - dest += 3; - source += 1; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: uchar_la_to_rgb -// Description: Recopies the given array of pixels, converting from -// luminance-alpha to RGB arrangement. -//////////////////////////////////////////////////////////////////// -static void -uchar_la_to_rgb(unsigned char *dest, const unsigned char *source, - int num_pixels) { - for (int i = 0; i < num_pixels; i++) { - dest[2] = dest[1] = dest[0] = source[0] * source[1] / 255; - dest += 3; - source += 2; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: restructure_image -// Description: Converts the pixels of the image to the appropriate -// format for TinyGL (i.e. GL_RGB). -//////////////////////////////////////////////////////////////////// -static PTA_uchar -restructure_image(Texture *tex) { - int num_pixels = tex->get_x_size() * tex->get_y_size(); - CPTA_uchar orig_image = tex->get_ram_image(); - PTA_uchar new_image = PTA_uchar::empty_array(num_pixels * 3); - - switch (tex->get_format()) { - case Texture::F_rgb: - case Texture::F_rgb5: - case Texture::F_rgb8: - case Texture::F_rgb12: - case Texture::F_rgb332: - uchar_bgr_to_rgb(new_image, orig_image, num_pixels); - break; - - case Texture::F_rgba: - case Texture::F_rgbm: - case Texture::F_rgba4: - case Texture::F_rgba5: - case Texture::F_rgba8: - case Texture::F_rgba12: - case Texture::F_rgba16: - case Texture::F_rgba32: - uchar_bgra_to_rgb(new_image, orig_image, num_pixels); - break; - - case Texture::F_luminance: - case Texture::F_alpha: - uchar_lum_to_rgb(new_image, orig_image, num_pixels); - break; - - case Texture::F_luminance_alphamask: - case Texture::F_luminance_alpha: - uchar_la_to_rgb(new_image, orig_image, num_pixels); - break; - - default: - break; - } - - return new_image; -} +static const ZB_fillTriangleFunc fill_tri_funcs +[2 /* alpha test: anone, abin (binary) */] +[2 /* ztest: znone, zless */] +[3 /* white, flat, smooth */] +[3 /* untextured, textured, perspective textured */] = { + { // alpha test anone + { + { ZB_fillTriangleFlat_anone_znone, + ZB_fillTriangleMapping_anone_znone, + ZB_fillTriangleMappingPerspective_anone_znone }, + { ZB_fillTriangleFlat_anone_znone, + ZB_fillTriangleMappingFlat_anone_znone, + ZB_fillTriangleMappingPerspectiveFlat_anone_znone }, + { ZB_fillTriangleSmooth_anone_znone, + ZB_fillTriangleMappingSmooth_anone_znone, + ZB_fillTriangleMappingPerspectiveSmooth_anone_znone }, + }, + { + { ZB_fillTriangleFlat_anone_zless, + ZB_fillTriangleMapping_anone_zless, + ZB_fillTriangleMappingPerspective_anone_zless }, + { ZB_fillTriangleFlat_anone_zless, + ZB_fillTriangleMappingFlat_anone_zless, + ZB_fillTriangleMappingPerspectiveFlat_anone_zless }, + { ZB_fillTriangleSmooth_anone_zless, + ZB_fillTriangleMappingSmooth_anone_zless, + ZB_fillTriangleMappingPerspectiveSmooth_anone_zless }, + }, + }, + { // alpha test abin + { + { ZB_fillTriangleFlat_abin_znone, + ZB_fillTriangleMapping_abin_znone, + ZB_fillTriangleMappingPerspective_abin_znone }, + { ZB_fillTriangleFlat_abin_znone, + ZB_fillTriangleMappingFlat_abin_znone, + ZB_fillTriangleMappingPerspectiveFlat_abin_znone }, + { ZB_fillTriangleSmooth_abin_znone, + ZB_fillTriangleMappingSmooth_abin_znone, + ZB_fillTriangleMappingPerspectiveSmooth_abin_znone }, + }, + { + { ZB_fillTriangleFlat_abin_zless, + ZB_fillTriangleMapping_abin_zless, + ZB_fillTriangleMappingPerspective_abin_zless }, + { ZB_fillTriangleFlat_abin_zless, + ZB_fillTriangleMappingFlat_abin_zless, + ZB_fillTriangleMappingPerspectiveFlat_abin_zless }, + { ZB_fillTriangleSmooth_abin_zless, + ZB_fillTriangleMappingSmooth_abin_zless, + ZB_fillTriangleMappingPerspectiveSmooth_abin_zless }, + }, + }, +}; static inline void tgl_vertex_transform(GLContext * c, GLVertex * v) { @@ -581,18 +503,17 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, gl_M4_Inv(&tmp, _c->matrix_stack_ptr[0]); gl_M4_Transpose(&_c->matrix_model_view_inv, &tmp); - } else { - // If we're not using lighting, go ahead and compose the - // modelview and projection matrices. - load_matrix(&_c->matrix_model_projection, - _projection_mat->compose(_internal_transform)); + } - /* test to accelerate computation */ - _c->matrix_model_projection_no_w_transform = 0; - float *m = &_c->matrix_model_projection.m[0][0]; - if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) { - _c->matrix_model_projection_no_w_transform = 1; - } + // Compose the modelview and projection matrices. + load_matrix(&_c->matrix_model_projection, + _projection_mat->compose(_internal_transform)); + + /* test to accelerate computation */ + _c->matrix_model_projection_no_w_transform = 0; + float *m = &_c->matrix_model_projection.m[0][0]; + if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) { + _c->matrix_model_projection_no_w_transform = 1; } _transform_stale = false; } @@ -740,6 +661,47 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, v->edge_flag = 0; } + // Set up the appropriate function callback for filling triangles, + // according to the current state. + + int alpha_test_state = 0; + if (_target._transparency->get_mode() != TransparencyAttrib::M_none) { + alpha_test_state = 1; + } + + int depth_test_state = 1; + if (_target._depth_test->get_mode() == DepthTestAttrib::M_none) { + depth_test_state = 0; + } + + ShadeModelAttrib::Mode shade_model = _target._shade_model->get_mode(); + if (!needs_normal && !needs_color) { + // With no per-vertex lighting, and no per-vertex colors, we might + // as well use the flat shading model. + shade_model = ShadeModelAttrib::M_flat; + } + int color_state = 2; // smooth + if (shade_model == ShadeModelAttrib::M_flat) { + color_state = 1; // flat + if (_c->current_color.X == 1.0f && + _c->current_color.Y == 1.0f && + _c->current_color.Z == 1.0f && + _c->current_color.W == 1.0f) { + color_state = 0; // white + } + } + + int texture_state = 0; // untextured + if (_c->texture_2d_enabled) { + texture_state = 2; // perspective-correct textures + if (_c->matrix_model_projection_no_w_transform) { + texture_state = 1; // non-perspective-correct textures + } + } + + _c->zb_fill_tri = fill_tri_funcs[alpha_test_state][depth_test_state][color_state][texture_state]; + //_c->zb_fill_tri = ZB_fillTriangleFlat_zless; + return true; } @@ -962,12 +924,6 @@ set_state_and_transform(const RenderState *target, _state._render_mode = _target._render_mode; } - if (_target._shade_model != _state._shade_model) { - PStatTimer timer(_draw_set_state_shade_model_pcollector); - do_issue_shade_model(); - _state._shade_model = _target._shade_model; - } - if ((_target._transparency != _state._transparency)|| (_target._color_write != _state._color_write)|| (_target._color_blend != _state._color_blend)) { @@ -1035,7 +991,7 @@ prepare_texture(Texture *tex) { } TinyTextureContext *gtc = new TinyTextureContext(_prepared_objects, tex); - glGenTextures(1, >c->_index); + gtc->_gltex = (GLTexture *)gl_zalloc(sizeof(GLTexture)); apply_texture(gtc); return gtc; @@ -1053,9 +1009,22 @@ void TinyGraphicsStateGuardian:: release_texture(TextureContext *tc) { TinyTextureContext *gtc = DCAST(TinyTextureContext, tc); - glDeleteTextures(1, >c->_index); + if (_c->current_texture == gtc->_gltex) { + _c->current_texture = NULL; + _c->zb->current_texture = NULL; + _c->texture_2d_enabled = false; + } + + for (int i = 0; i < MAX_TEXTURE_LEVELS; i++) { + GLImage *im = >c->_gltex->images[i]; + if (im->pixmap != NULL) { + gl_free(im->pixmap); + } + } + + gl_free(gtc->_gltex); + gtc->_gltex = NULL; - gtc->_index = 0; delete gtc; } @@ -1183,25 +1152,6 @@ do_issue_transform() { _transform_stale = true; } -//////////////////////////////////////////////////////////////////// -// Function: TinyGraphicsStateGuardian::do_issue_shade_model -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void TinyGraphicsStateGuardian:: -do_issue_shade_model() { - const ShadeModelAttrib *attrib = _target._shade_model; - switch (attrib->get_mode()) { - case ShadeModelAttrib::M_smooth: - glShadeModel(GL_SMOOTH); - break; - - case ShadeModelAttrib::M_flat: - glShadeModel(GL_FLAT); - break; - } -} - //////////////////////////////////////////////////////////////////// // Function: TinyGraphicsStateGuardian::do_issue_render_mode // Access: Protected @@ -1339,7 +1289,7 @@ do_issue_material() { //////////////////////////////////////////////////////////////////// void TinyGraphicsStateGuardian:: do_issue_texture() { - glDisable(GL_TEXTURE_2D); + _c->texture_2d_enabled = false; int num_stages = _effective_texture->get_num_on_ff_stages(); if (num_stages == 0) { @@ -1359,7 +1309,6 @@ do_issue_texture() { } // Then, turn on the current texture mode. - glEnable(GL_TEXTURE_2D); apply_texture(tc); /* @@ -1508,12 +1457,13 @@ apply_texture(TextureContext *tc) { TinyTextureContext *gtc = DCAST(TinyTextureContext, tc); gtc->set_active(true); - glBindTexture(GL_TEXTURE_2D, gtc->_index); + _c->current_texture = gtc->_gltex; + _c->texture_2d_enabled = true; if (gtc->was_image_modified()) { // If the texture image was modified, reload the texture. if (!upload_texture(gtc)) { - glDisable(GL_TEXTURE_2D); + _c->texture_2d_enabled = false; } gtc->mark_loaded(); @@ -1522,6 +1472,8 @@ apply_texture(TextureContext *tc) { // reload the texture. gtc->mark_loaded(); } + + _c->zb->current_texture = (PIXEL *)gtc->_gltex->images[0].pixmap; } //////////////////////////////////////////////////////////////////// @@ -1541,24 +1493,70 @@ upload_texture(TinyTextureContext *gtc) { tinydisplay_cat.debug() << "loading texture " << tex->get_name() << "\n"; } - CPTA_uchar image = tex->get_ram_image(); - nassertr(!image.is_null(), false) - - int width = tex->get_x_size(); - int height = tex->get_y_size(); - - PTA_uchar new_image = restructure_image(tex); - const unsigned char *image_ptr = new_image.p(); - #ifdef DO_PSTATS - _data_transferred_pcollector.add_level(new_image.size()); + _data_transferred_pcollector.add_level(tex->get_ram_image_size()); #endif - glTexImage2D(GL_TEXTURE_2D, 0, 3, - width, height, 0, - GL_RGB, GL_UNSIGNED_BYTE, (void *)image_ptr); + + // Internal texture size is always 256 x 256 x 4. + static const int iwidth = 256; + static const int iheight = 256; + static const int ibytecount = iwidth * iheight * 4; + + GLImage *im = >c->_gltex->images[0]; + im->xsize = iwidth; + im->ysize = iheight; + if (im->pixmap == NULL) { + im->pixmap = gl_malloc(ibytecount); + } + + switch (tex->get_format()) { + case Texture::F_rgb: + case Texture::F_rgb5: + case Texture::F_rgb8: + case Texture::F_rgb12: + case Texture::F_rgb332: + copy_rgb_image(im, tex); + break; + + case Texture::F_rgba: + case Texture::F_rgbm: + case Texture::F_rgba4: + case Texture::F_rgba5: + case Texture::F_rgba8: + case Texture::F_rgba12: + case Texture::F_rgba16: + case Texture::F_rgba32: + copy_rgba_image(im, tex); + break; + + case Texture::F_luminance: + copy_lum_image(im, tex); + break; + + case Texture::F_red: + copy_one_channel_image(im, tex, 0); + break; + + case Texture::F_green: + copy_one_channel_image(im, tex, 1); + break; + + case Texture::F_blue: + copy_one_channel_image(im, tex, 2); + break; + + case Texture::F_alpha: + copy_alpha_image(im, tex); + break; + + case Texture::F_luminance_alphamask: + case Texture::F_luminance_alpha: + copy_la_image(im, tex); + break; + } #ifdef DO_PSTATS - gtc->update_data_size_bytes(256 * 256 * 3); + gtc->update_data_size_bytes(ibytecount); #endif tex->texture_uploaded(); @@ -1566,6 +1564,339 @@ upload_texture(TinyTextureContext *gtc) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: TinyGraphicsStateGuardian::copy_lum_image +// Access: Private, Static +// Description: Copies and scales the one-channel luminance image +// from the texture into the indicated GLImage pixmap. +//////////////////////////////////////////////////////////////////// +void TinyGraphicsStateGuardian:: +copy_lum_image(GLImage *im, Texture *tex) { + nassertv(tex->get_num_components() == 1); + + int xsize_src = tex->get_x_size(); + int ysize_src = tex->get_y_size(); + CPTA_uchar src_image = tex->get_ram_image(); + nassertv(!src_image.is_null()); + const unsigned char *src = src_image.p(); + + // Component width, and offset to the high-order byte. + int cw = tex->get_component_width(); +#ifdef WORDS_BIGENDIAN + // Big-endian: the high-order byte is always first. + static const int co = 0; +#else + // Little-endian: the high-order byte is last. + int co = cw - 1; +#endif + + int xsize_dest = im->xsize; + int ysize_dest = im->xsize; + unsigned char *dest = (unsigned char *)im->pixmap; + nassertv(dest != NULL); + + int sx_inc = (int)((float)(xsize_src) / (float)(xsize_dest)); + int sy_inc = (int)((float)(ysize_src) / (float)(ysize_dest)); + + unsigned char *dpix = dest; + int syn = 0; + for (int dy = 0; dy < ysize_dest; dy++) { + int sy = syn / ysize_dest; + int sxn = 0; + for (int dx = 0; dx < xsize_dest; dx++) { + int sx = sxn / xsize_dest; + const unsigned char *spix = src + (sy * xsize_src + sx) * 1 * cw; + + dpix[0] = spix[co]; + dpix[1] = spix[co]; + dpix[2] = spix[co]; + dpix[3] = 0xff; + + dpix += 4; + sxn += xsize_src; + } + syn += ysize_src; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TinyGraphicsStateGuardian::copy_alpha_image +// Access: Private, Static +// Description: Copies and scales the one-channel alpha image +// from the texture into the indicated GLImage pixmap. +//////////////////////////////////////////////////////////////////// +void TinyGraphicsStateGuardian:: +copy_alpha_image(GLImage *im, Texture *tex) { + nassertv(tex->get_num_components() == 1); + + int xsize_src = tex->get_x_size(); + int ysize_src = tex->get_y_size(); + CPTA_uchar src_image = tex->get_ram_image(); + nassertv(!src_image.is_null()); + const unsigned char *src = src_image.p(); + + // Component width, and offset to the high-order byte. + int cw = tex->get_component_width(); +#ifdef WORDS_BIGENDIAN + // Big-endian: the high-order byte is always first. + static const int co = 0; +#else + // Little-endian: the high-order byte is last. + int co = cw - 1; +#endif + + int xsize_dest = im->xsize; + int ysize_dest = im->xsize; + unsigned char *dest = (unsigned char *)im->pixmap; + nassertv(dest != NULL); + + int sx_inc = (int)((float)(xsize_src) / (float)(xsize_dest)); + int sy_inc = (int)((float)(ysize_src) / (float)(ysize_dest)); + + unsigned char *dpix = dest; + int syn = 0; + for (int dy = 0; dy < ysize_dest; dy++) { + int sy = syn / ysize_dest; + int sxn = 0; + for (int dx = 0; dx < xsize_dest; dx++) { + int sx = sxn / xsize_dest; + const unsigned char *spix = src + (sy * xsize_src + sx) * 1 * cw; + + dpix[0] = 0xff; + dpix[1] = 0xff; + dpix[2] = 0xff; + dpix[3] = spix[co]; + + dpix += 4; + sxn += xsize_src; + } + syn += ysize_src; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TinyGraphicsStateGuardian::copy_one_channel_image +// Access: Private, Static +// Description: Copies and scales the one-channel image (with a +// single channel, e.g. red, green, or blue) from +// the texture into the indicated GLImage pixmap. +//////////////////////////////////////////////////////////////////// +void TinyGraphicsStateGuardian:: +copy_one_channel_image(GLImage *im, Texture *tex, int channel) { + nassertv(tex->get_num_components() == 1); + + int xsize_src = tex->get_x_size(); + int ysize_src = tex->get_y_size(); + CPTA_uchar src_image = tex->get_ram_image(); + nassertv(!src_image.is_null()); + const unsigned char *src = src_image.p(); + + // Component width, and offset to the high-order byte. + int cw = tex->get_component_width(); +#ifdef WORDS_BIGENDIAN + // Big-endian: the high-order byte is always first. + static const int co = 0; +#else + // Little-endian: the high-order byte is last. + int co = cw - 1; +#endif + + int xsize_dest = im->xsize; + int ysize_dest = im->xsize; + unsigned char *dest = (unsigned char *)im->pixmap; + nassertv(dest != NULL); + + int sx_inc = (int)((float)(xsize_src) / (float)(xsize_dest)); + int sy_inc = (int)((float)(ysize_src) / (float)(ysize_dest)); + + unsigned char *dpix = dest; + int syn = 0; + for (int dy = 0; dy < ysize_dest; dy++) { + int sy = syn / ysize_dest; + int sxn = 0; + for (int dx = 0; dx < xsize_dest; dx++) { + int sx = sxn / xsize_dest; + const unsigned char *spix = src + (sy * xsize_src + sx) * 1 * cw; + + dpix[0] = 0; + dpix[1] = 0; + dpix[2] = 0; + dpix[3] = 0xff; + dpix[channel] = spix[co]; + + dpix += 4; + sxn += xsize_src; + } + syn += ysize_src; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TinyGraphicsStateGuardian::copy_la_image +// Access: Private, Static +// Description: Copies and scales the two-channel luminance-alpha +// image from the texture into the indicated GLImage +// pixmap. +//////////////////////////////////////////////////////////////////// +void TinyGraphicsStateGuardian:: +copy_la_image(GLImage *im, Texture *tex) { + nassertv(tex->get_num_components() == 2); + + int xsize_src = tex->get_x_size(); + int ysize_src = tex->get_y_size(); + CPTA_uchar src_image = tex->get_ram_image(); + nassertv(!src_image.is_null()); + const unsigned char *src = src_image.p(); + + // Component width, and offset to the high-order byte. + int cw = tex->get_component_width(); +#ifdef WORDS_BIGENDIAN + // Big-endian: the high-order byte is always first. + static const int co = 0; +#else + // Little-endian: the high-order byte is last. + int co = cw - 1; +#endif + + int xsize_dest = im->xsize; + int ysize_dest = im->xsize; + unsigned char *dest = (unsigned char *)im->pixmap; + nassertv(dest != NULL); + + int sx_inc = (int)((float)(xsize_src) / (float)(xsize_dest)); + int sy_inc = (int)((float)(ysize_src) / (float)(ysize_dest)); + + unsigned char *dpix = dest; + int syn = 0; + for (int dy = 0; dy < ysize_dest; dy++) { + int sy = syn / ysize_dest; + int sxn = 0; + for (int dx = 0; dx < xsize_dest; dx++) { + int sx = sxn / xsize_dest; + const unsigned char *spix = src + (sy * xsize_src + sx) * 2 * cw; + + dpix[0] = spix[co]; + dpix[1] = spix[co]; + dpix[2] = spix[co]; + dpix[3] = spix[cw + co]; + + dpix += 4; + sxn += xsize_src; + } + syn += ysize_src; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TinyGraphicsStateGuardian::copy_rgb_image +// Access: Private, Static +// Description: Copies and scales the three-channel RGB image from +// the texture into the indicated GLImage pixmap. +//////////////////////////////////////////////////////////////////// +void TinyGraphicsStateGuardian:: +copy_rgb_image(GLImage *im, Texture *tex) { + nassertv(tex->get_num_components() == 3); + + int xsize_src = tex->get_x_size(); + int ysize_src = tex->get_y_size(); + CPTA_uchar src_image = tex->get_ram_image(); + nassertv(!src_image.is_null()); + const unsigned char *src = src_image.p(); + + // Component width, and offset to the high-order byte. + int cw = tex->get_component_width(); +#ifdef WORDS_BIGENDIAN + // Big-endian: the high-order byte is always first. + static const int co = 0; +#else + // Little-endian: the high-order byte is last. + int co = cw - 1; +#endif + + int xsize_dest = im->xsize; + int ysize_dest = im->xsize; + unsigned char *dest = (unsigned char *)im->pixmap; + nassertv(dest != NULL); + + int sx_inc = (int)((float)(xsize_src) / (float)(xsize_dest)); + int sy_inc = (int)((float)(ysize_src) / (float)(ysize_dest)); + + unsigned char *dpix = dest; + int syn = 0; + for (int dy = 0; dy < ysize_dest; dy++) { + int sy = syn / ysize_dest; + int sxn = 0; + for (int dx = 0; dx < xsize_dest; dx++) { + int sx = sxn / xsize_dest; + const unsigned char *spix = src + (sy * xsize_src + sx) * 3 * cw; + + dpix[0] = spix[co]; + dpix[1] = spix[cw + co]; + dpix[2] = spix[cw + cw + co]; + dpix[3] = 0xff; + + dpix += 4; + sxn += xsize_src; + } + syn += ysize_src; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TinyGraphicsStateGuardian::copy_rgba_image +// Access: Private, Static +// Description: Copies and scales the four-channel RGBA image from +// the texture into the indicated GLImage pixmap. +//////////////////////////////////////////////////////////////////// +void TinyGraphicsStateGuardian:: +copy_rgba_image(GLImage *im, Texture *tex) { + nassertv(tex->get_num_components() == 4); + + int xsize_src = tex->get_x_size(); + int ysize_src = tex->get_y_size(); + CPTA_uchar src_image = tex->get_ram_image(); + nassertv(!src_image.is_null()); + const unsigned char *src = src_image.p(); + + // Component width, and offset to the high-order byte. + int cw = tex->get_component_width(); +#ifdef WORDS_BIGENDIAN + // Big-endian: the high-order byte is always first. + static const int co = 0; +#else + // Little-endian: the high-order byte is last. + int co = cw - 1; +#endif + + int xsize_dest = im->xsize; + int ysize_dest = im->xsize; + unsigned char *dest = (unsigned char *)im->pixmap; + nassertv(dest != NULL); + + int sx_inc = (int)((float)(xsize_src) / (float)(xsize_dest)); + int sy_inc = (int)((float)(ysize_src) / (float)(ysize_dest)); + + unsigned char *dpix = dest; + int syn = 0; + for (int dy = 0; dy < ysize_dest; dy++) { + int sy = syn / ysize_dest; + int sxn = 0; + for (int dx = 0; dx < xsize_dest; dx++) { + int sx = sxn / xsize_dest; + const unsigned char *spix = src + (sy * xsize_src + sx) * 4 * cw; + + dpix[0] = spix[co]; + dpix[1] = spix[cw + co]; + dpix[2] = spix[cw + cw + co]; + dpix[3] = spix[cw + cw + cw + co]; + + dpix += 4; + sxn += xsize_src; + } + syn += ysize_src; + } +} + //////////////////////////////////////////////////////////////////// // Function: TinyGraphicsStateGuardian::load_matrix // Access: Private, Static diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h index bae6bc9dd3..c1c30b0d7b 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.h +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.h @@ -33,6 +33,7 @@ extern "C" { class TinyTextureContext; struct GLContext; struct GLVertex; +struct GLImage; //////////////////////////////////////////////////////////////////// @@ -98,7 +99,6 @@ private: void do_issue_transform(); void do_issue_render_mode(); void do_issue_cull_face(); - void do_issue_shade_model(); void do_issue_material(); void do_issue_texture(); void do_issue_blending(); @@ -106,6 +106,13 @@ private: void apply_texture(TextureContext *tc); bool upload_texture(TinyTextureContext *gtc); + static void copy_lum_image(GLImage *im, Texture *tex); + static void copy_alpha_image(GLImage *im, Texture *tex); + static void copy_one_channel_image(GLImage *im, Texture *tex, int channel); + static void copy_la_image(GLImage *im, Texture *tex); + static void copy_rgb_image(GLImage *im, Texture *tex); + static void copy_rgba_image(GLImage *im, Texture *tex); + static void load_matrix(M4 *matrix, const TransformState *transform); INLINE static GLenum get_light_id(int index); diff --git a/panda/src/tinydisplay/tinyGraphicsWindow.cxx b/panda/src/tinydisplay/tinyGraphicsWindow.cxx index 553276eb3a..fd79d42d73 100644 --- a/panda/src/tinydisplay/tinyGraphicsWindow.cxx +++ b/panda/src/tinydisplay/tinyGraphicsWindow.cxx @@ -181,7 +181,7 @@ process_events() { system_changed_properties(properties); _screen = SDL_SetVideoMode(_properties.get_x_size(), _properties.get_y_size(), 32, _flags); ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size()); - _pitch = _screen->pitch * TGL_FEATURE_RENDER_BITS / _screen->format->BitsPerPixel; + _pitch = _screen->pitch * 32 / _screen->format->BitsPerPixel; break; case SDL_QUIT: @@ -325,7 +325,7 @@ create_frame_buffer() { _frame_buffer = ZB_open(_properties.get_x_size(), _properties.get_y_size(), mode, 0, 0, 0, 0); - _pitch = _screen->pitch * TGL_FEATURE_RENDER_BITS / _screen->format->BitsPerPixel; + _pitch = _screen->pitch * 32 / _screen->format->BitsPerPixel; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/tinydisplay/tinyTextureContext.I b/panda/src/tinydisplay/tinyTextureContext.I index 68f5390f8d..d8b05d1560 100644 --- a/panda/src/tinydisplay/tinyTextureContext.I +++ b/panda/src/tinydisplay/tinyTextureContext.I @@ -26,5 +26,15 @@ INLINE TinyTextureContext:: TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex) : TextureContext(pgo, tex) { - _index = 0; + _gltex = NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: TinyTextureContext::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TinyTextureContext:: +~TinyTextureContext() { + nassertv(_gltex == NULL); } diff --git a/panda/src/tinydisplay/tinyTextureContext.h b/panda/src/tinydisplay/tinyTextureContext.h index 622447ac44..b4a68493bc 100644 --- a/panda/src/tinydisplay/tinyTextureContext.h +++ b/panda/src/tinydisplay/tinyTextureContext.h @@ -24,6 +24,8 @@ #include "deletedChain.h" #include "tinygl.h" +struct GLTexture; + //////////////////////////////////////////////////////////////////// // Class : TinyTextureContext // Description : @@ -33,8 +35,9 @@ public: INLINE TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex); ALLOC_DELETED_CHAIN(TinyTextureContext); - // This is the GL "name" of the texture object. - GLuint _index; + INLINE ~TinyTextureContext(); + + GLTexture *_gltex; public: static TypeHandle get_class_type() { diff --git a/panda/src/tinydisplay/zbuffer.c b/panda/src/tinydisplay/zbuffer.c index cbf7a06b6d..ee9131022b 100644 --- a/panda/src/tinydisplay/zbuffer.c +++ b/panda/src/tinydisplay/zbuffer.c @@ -132,230 +132,6 @@ static void ZB_copyBuffer(ZBuffer * zb, } } -#if TGL_FEATURE_RENDER_BITS == 16 - -/* 32 bpp copy */ - -#ifdef TGL_FEATURE_32_BITS - -#define RGB16_TO_RGB32(p0,p1,v)\ -{\ - unsigned int g,b,gb;\ - g = (v & 0x07E007E0) << 5;\ - b = (v & 0x001F001F) << 3;\ - gb = g | b;\ - p0 = (gb & 0x0000FFFF) | ((v & 0x0000F800) << 8);\ - p1 = (gb >> 16) | ((v & 0xF8000000) >> 8);\ -} - -static void ZB_copyFrameBufferRGB32(ZBuffer * zb, - void *buf, - int linesize) -{ - unsigned short *q; - unsigned int *p, *p1, v, w0, w1; - int y, n; - - q = zb->pbuf; - p1 = (unsigned int *) buf; - - for (y = 0; y < zb->ysize; y++) { - p = p1; - n = zb->xsize >> 2; - do { - v = *(unsigned int *) q; -#if BYTE_ORDER == BIG_ENDIAN - RGB16_TO_RGB32(w1, w0, v); -#else - RGB16_TO_RGB32(w0, w1, v); -#endif - p[0] = w0; - p[1] = w1; - - v = *(unsigned int *) (q + 2); -#if BYTE_ORDER == BIG_ENDIAN - RGB16_TO_RGB32(w1, w0, v); -#else - RGB16_TO_RGB32(w0, w1, v); -#endif - p[2] = w0; - p[3] = w1; - - q += 4; - p += 4; - } while (--n > 0); - - p1 += linesize; - } -} - -#endif - -/* 24 bit packed pixel handling */ - -#ifdef TGL_FEATURE_24_BITS - -/* order: RGBR GBRG BRGB */ - -/* XXX: packed pixel 24 bit support not tested */ -/* XXX: big endian case not optimised */ - -#if BYTE_ORDER == BIG_ENDIAN - -#define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\ -{\ - unsigned int r1,g1,b1,gb1,g2,b2,gb2;\ - v1 = (v1 << 16) | (v1 >> 16);\ - v2 = (v2 << 16) | (v2 >> 16);\ - r1 = (v1 & 0xF800F800);\ - g1 = (v1 & 0x07E007E0) << 5;\ - b1 = (v1 & 0x001F001F) << 3;\ - gb1 = g1 | b1;\ - p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\ - g2 = (v2 & 0x07E007E0) << 5;\ - b2 = (v2 & 0x001F001F) << 3;\ - gb2 = g2 | b2;\ - p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\ - p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\ -} - -#else - -#define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\ -{\ - unsigned int r1,g1,b1,gb1,g2,b2,gb2;\ - r1 = (v1 & 0xF800F800);\ - g1 = (v1 & 0x07E007E0) << 5;\ - b1 = (v1 & 0x001F001F) << 3;\ - gb1 = g1 | b1;\ - p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\ - g2 = (v2 & 0x07E007E0) << 5;\ - b2 = (v2 & 0x001F001F) << 3;\ - gb2 = g2 | b2;\ - p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\ - p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\ -} - -#endif - -static void ZB_copyFrameBufferRGB24(ZBuffer * zb, - void *buf, - int linesize) -{ - unsigned short *q; - unsigned int *p, w0, w1, w2, v0, v1; - char *p1; - int y, n; - - q = zb->pbuf; - p1 = buf; - linesize = linesize * 3; - - for (y = 0; y < zb->ysize; y++) { - p = (unsigned int *)p1; - n = zb->xsize >> 2; - do { - v0 = *(unsigned int *) q; - v1 = *(unsigned int *) (q + 2); - RGB16_TO_RGB24(w0, w1, w2, v0, v1); - p[0] = w0; - p[1] = w1; - p[2] = w2; - - q += 4; - p += 3; - } while (--n > 0); - p1 += linesize; - } -} - -#endif - -void ZB_copyFrameBuffer(ZBuffer * zb, void *buf, - int linesize) -{ - switch (zb->mode) { -#ifdef TGL_FEATURE_8_BITS - case ZB_MODE_INDEX: - ZB_ditherFrameBuffer(zb, buf, linesize >> 1); - break; -#endif -#ifdef TGL_FEATURE_16_BITS - case ZB_MODE_5R6G5B: - ZB_copyBuffer(zb, buf, linesize); - break; -#endif -#ifdef TGL_FEATURE_32_BITS - case ZB_MODE_RGBA: - ZB_copyFrameBufferRGB32(zb, buf, linesize >> 1); - break; -#endif -#ifdef TGL_FEATURE_24_BITS - case ZB_MODE_RGB24: - ZB_copyFrameBufferRGB24(zb, buf, linesize >> 1); - break; -#endif - default: - assert(0); - } -} - -#endif /* TGL_FEATURE_RENDER_BITS == 16 */ - -#if TGL_FEATURE_RENDER_BITS == 24 - -#define RGB24_TO_RGB16(r, g, b) \ - ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) - -/* XXX: not optimized */ -static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb, - void *buf, int linesize) -{ - PIXEL *q; - unsigned short *p, *p1; - int y, n; - - q = zb->pbuf; - p1 = (unsigned short *) buf; - - for (y = 0; y < zb->ysize; y++) { - p = p1; - n = zb->xsize >> 2; - do { - p[0] = RGB24_TO_RGB16(q[0], q[1], q[2]); - p[1] = RGB24_TO_RGB16(q[3], q[4], q[5]); - p[2] = RGB24_TO_RGB16(q[6], q[7], q[8]); - p[3] = RGB24_TO_RGB16(q[9], q[10], q[11]); - q = (PIXEL *)((char *)q + 4 * PSZB); - p += 4; - } while (--n > 0); - p1 = (unsigned short *)((char *)p1 + linesize); - } -} - -void ZB_copyFrameBuffer(ZBuffer * zb, void *buf, - int linesize) -{ - switch (zb->mode) { -#ifdef TGL_FEATURE_16_BITS - case ZB_MODE_5R6G5B: - ZB_copyFrameBuffer5R6G5B(zb, buf, linesize); - break; -#endif -#ifdef TGL_FEATURE_24_BITS - case ZB_MODE_RGB24: - ZB_copyBuffer(zb, buf, linesize); - break; -#endif - default: - assert(0); - } -} - -#endif /* TGL_FEATURE_RENDER_BITS == 24 */ - -#if TGL_FEATURE_RENDER_BITS == 32 - #define RGB32_TO_RGB16(v) \ (((v >> 8) & 0xf800) | (((v) >> 5) & 0x07e0) | (((v) & 0xff) >> 3)) @@ -404,8 +180,6 @@ void ZB_copyFrameBuffer(ZBuffer * zb, void *buf, } } -#endif /* TGL_FEATURE_RENDER_BITS == 32 */ - /* * adr must be aligned on an 'int' @@ -489,9 +263,7 @@ void memset_RGB24(void *adr,int r, int v, int b,long count) void ZB_clear(ZBuffer * zb, int clear_z, int z, int clear_color, int r, int g, int b) { -#if TGL_FEATURE_RENDER_BITS != 24 int color; -#endif int y; PIXEL *pp; @@ -501,17 +273,8 @@ void ZB_clear(ZBuffer * zb, int clear_z, int z, if (clear_color) { pp = zb->pbuf; for (y = 0; y < zb->ysize; y++) { -#if TGL_FEATURE_RENDER_BITS == 15 || TGL_FEATURE_RENDER_BITS == 16 - color = RGB_TO_PIXEL(r, g, b); - memset_s(pp, color, zb->xsize); -#elif TGL_FEATURE_RENDER_BITS == 32 color = RGB_TO_PIXEL(r, g, b); memset_l(pp, color, zb->xsize); -#elif TGL_FEATURE_RENDER_BITS == 24 - memset_RGB24(pp,r>>8,g>>8,b>>8,zb->xsize); -#else -#error TODO -#endif pp = (PIXEL *) ((char *) pp + zb->linesize); } } diff --git a/panda/src/tinydisplay/zbuffer.h b/panda/src/tinydisplay/zbuffer.h index 42fcbe8a8b..60c6f63775 100644 --- a/panda/src/tinydisplay/zbuffer.h +++ b/panda/src/tinydisplay/zbuffer.h @@ -16,12 +16,14 @@ #define ZB_POINT_T_MIN ( (1<<21) ) #define ZB_POINT_T_MAX ( (1<<30)-(1<<21) ) -#define ZB_POINT_RED_MIN ( (1<<10) ) -#define ZB_POINT_RED_MAX ( (1<<16)-(1<<10) ) -#define ZB_POINT_GREEN_MIN ( (1<<9) ) -#define ZB_POINT_GREEN_MAX ( (1<<16)-(1<<9) ) -#define ZB_POINT_BLUE_MIN ( (1<<10) ) -#define ZB_POINT_BLUE_MAX ( (1<<16)-(1<<10) ) +#define ZB_POINT_RED_MIN 0x0000 +#define ZB_POINT_RED_MAX 0xff00 +#define ZB_POINT_GREEN_MIN 0x0000 +#define ZB_POINT_GREEN_MAX 0xff00 +#define ZB_POINT_BLUE_MIN 0x0000 +#define ZB_POINT_BLUE_MAX 0xff00 +#define ZB_POINT_ALPHA_MIN 0x0000 +#define ZB_POINT_ALPHA_MAX 0xff00 /* display modes */ #define ZB_MODE_5R6G5B 1 /* true color 16 bits */ @@ -30,56 +32,18 @@ #define ZB_MODE_RGB24 4 /* 24 bit rgb mode */ #define ZB_NB_COLORS 225 /* number of colors for 8 bit display */ -#if TGL_FEATURE_RENDER_BITS == 15 - -#define RGB_TO_PIXEL(r,g,b) \ - ((((r) >> 1) & 0x7c00) | (((g) >> 6) & 0x03e0) | ((b) >> 11)) -#define PIXEL_R(p) (((p) & 0x7c00) << 1) -#define PIXEL_G(p) (((p) & 0x03e0) << 6) -#define PIXEL_B(p) (((p) & 0x001f) << 11) -typedef unsigned short PIXEL; -/* bytes per pixel */ -#define PSZB 2 -/* bits per pixel = (1 << PSZH) */ -#define PSZSH 4 - -#elif TGL_FEATURE_RENDER_BITS == 16 - -/* 16 bit mode */ -#define RGB_TO_PIXEL(r,g,b) \ - (((r) & 0xF800) | (((g) >> 5) & 0x07E0) | ((b) >> 11)) -#define PIXEL_R(p) (((p) & 0xf800)) -#define PIXEL_G(p) (((p) & 0x07e0) << 5) -#define PIXEL_B(p) (((p) & 0x001f) << 11) -typedef unsigned short PIXEL; -#define PSZB 2 -#define PSZSH 4 - -#elif TGL_FEATURE_RENDER_BITS == 24 - -#define RGB_TO_PIXEL(r,g,b) \ - ((((r) << 8) & 0xff0000) | ((g) & 0xff00) | ((b) >> 8)) -typedef unsigned char PIXEL; -#define PSZB 3 -#define PSZSH 5 - -#elif TGL_FEATURE_RENDER_BITS == 32 - #define RGB_TO_PIXEL(r,g,b) \ ((((r) << 8) & 0xff0000) | ((g) & 0xff00) | ((b) >> 8)) +#define RGBA_TO_PIXEL(r,g,b,a) \ + ((((a) << 16) & 0xff000000) | (((r) << 8) & 0xff0000) | ((g) & 0xff00) | ((b) >> 8)) #define PIXEL_R(p) (((p) & 0xff0000) >> 8) #define PIXEL_G(p) ((p) & 0xff00) #define PIXEL_B(p) (((p) & 0x00ff) << 8) +#define PIXEL_A(p) (((p) & 0xff000000) >> 16) typedef unsigned int PIXEL; #define PSZB 4 #define PSZSH 5 -#else - -#error Incorrect number of bits per pixel - -#endif - #define PIXEL_MULT(p1, p2) \ RGB_TO_PIXEL((PIXEL_R(p1) * PIXEL_R(p2)) >> 16, \ (PIXEL_G(p1) * PIXEL_G(p2)) >> 16, \ @@ -104,7 +68,7 @@ typedef struct { typedef struct { int x,y,z; /* integer coordinates in the zbuffer */ int s,t; /* coordinates for the mapping */ - int r,g,b; /* color indexes */ + int r,g,b,a; /* color indexes */ float sz,tz; /* temporary coordinates for mapping */ } ZBufferPoint; @@ -142,20 +106,80 @@ void ZB_line_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2); /* ztriangle.c */ -void ZB_setTexture(ZBuffer *zb, PIXEL *texture); - -void ZB_fillTriangleFlat(ZBuffer *zb, +void ZB_fillTriangleFlat_anone_znone(ZBuffer *zb, ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); - -void ZB_fillTriangleSmooth(ZBuffer *zb, +void ZB_fillTriangleSmooth_anone_znone(ZBuffer *zb, ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); -void ZB_fillTriangleMapping(ZBuffer *zb, +void ZB_fillTriangleMapping_anone_znone(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleMappingFlat_anone_znone(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleMappingSmooth_anone_znone(ZBuffer *zb, ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); -void ZB_fillTriangleMappingPerspective(ZBuffer *zb, +void ZB_fillTriangleMappingPerspective_anone_znone(ZBuffer *zb, ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); -void ZB_fillTriangleMappingSmooth(ZBuffer *zb, +void ZB_fillTriangleMappingPerspectiveFlat_anone_znone(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); +void ZB_fillTriangleMappingPerspectiveSmooth_anone_znone(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); + +void ZB_fillTriangleFlat_anone_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleSmooth_anone_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); + +void ZB_fillTriangleMapping_anone_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleMappingFlat_anone_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleMappingSmooth_anone_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); + +void ZB_fillTriangleMappingPerspective_anone_zless(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); +void ZB_fillTriangleMappingPerspectiveFlat_anone_zless(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); +void ZB_fillTriangleMappingPerspectiveSmooth_anone_zless(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); + +void ZB_fillTriangleFlat_abin_znone(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleSmooth_abin_znone(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); + +void ZB_fillTriangleMapping_abin_znone(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleMappingFlat_abin_znone(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleMappingSmooth_abin_znone(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); + +void ZB_fillTriangleMappingPerspective_abin_znone(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); +void ZB_fillTriangleMappingPerspectiveFlat_abin_znone(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); +void ZB_fillTriangleMappingPerspectiveSmooth_abin_znone(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); + +void ZB_fillTriangleFlat_abin_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleSmooth_abin_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); + +void ZB_fillTriangleMapping_abin_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleMappingFlat_abin_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); +void ZB_fillTriangleMappingSmooth_abin_zless(ZBuffer *zb, + ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); + +void ZB_fillTriangleMappingPerspective_abin_zless(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); +void ZB_fillTriangleMappingPerspectiveFlat_abin_zless(ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); +void ZB_fillTriangleMappingPerspectiveSmooth_abin_zless(ZBuffer *zb, ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); diff --git a/panda/src/tinydisplay/zfeatures.h b/panda/src/tinydisplay/zfeatures.h index 07c9ac543b..c8e4a1ba73 100644 --- a/panda/src/tinydisplay/zfeatures.h +++ b/panda/src/tinydisplay/zfeatures.h @@ -29,36 +29,11 @@ #define TGL_FEATURE_DISPLAYLISTS 1 #define TGL_FEATURE_POLYGON_OFFSET 1 -/* - * Matrix of internal and external pixel formats supported. 'Y' means - * supported. - * - * External 8 16 24 32 - * Internal - * 15 . . . . - * 16 Y Y Y Y - * 24 . Y Y . - * 32 . Y . Y - * - * - * 15 bpp does not work yet (although it is easy to add it - ask me if - * you need it). - * - * Internal pixel format: see TGL_FEATURE_RENDER_BITS - * External pixel format: see TGL_FEATURE_xxx_BITS - */ - -/* enable various convertion code from internal pixel format (usually - 16 bits per pixel) to any external format */ +/* enable various conversion code from internal pixel format (32 bits + per pixel) to any external format */ #define TGL_FEATURE_16_BITS 1 //#define TGL_FEATURE_8_BITS 1 #define TGL_FEATURE_24_BITS 1 #define TGL_FEATURE_32_BITS 1 - -//#define TGL_FEATURE_RENDER_BITS 15 -//#define TGL_FEATURE_RENDER_BITS 16 -//#define TGL_FEATURE_RENDER_BITS 24 -#define TGL_FEATURE_RENDER_BITS 32 - #endif /* _tgl_features_h_ */ diff --git a/panda/src/tinydisplay/zgl.h b/panda/src/tinydisplay/zgl.h index b242627ded..a47e03c56b 100644 --- a/panda/src/tinydisplay/zgl.h +++ b/panda/src/tinydisplay/zgl.h @@ -211,6 +211,7 @@ typedef struct GLContext { int cull_face_enabled; int normalize_enabled; gl_draw_triangle_func draw_triangle_front,draw_triangle_back; + ZB_fillTriangleFunc zb_fill_tri; /* selection */ int render_mode; diff --git a/panda/src/tinydisplay/zline.c b/panda/src/tinydisplay/zline.c index 561064b0c2..a9cccaa48e 100644 --- a/panda/src/tinydisplay/zline.c +++ b/panda/src/tinydisplay/zline.c @@ -13,13 +13,7 @@ void ZB_plot(ZBuffer * zb, ZBufferPoint * p) pp = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p->y + p->x * PSZB); zz = p->z >> ZB_POINT_Z_FRAC_BITS; if (ZCMP(zz, *pz)) { -#if TGL_FEATURE_RENDER_BITS == 24 - pp[0]=p->r>>8; - pp[1]=p->g>>8; - pp[2]=p->b>>8; -#else *pp = RGB_TO_PIXEL(p->r, p->g, p->b); -#endif *pz = zz; } } diff --git a/panda/src/tinydisplay/zline.h b/panda/src/tinydisplay/zline.h index 982b3552c0..128870ee3a 100644 --- a/panda/src/tinydisplay/zline.h +++ b/panda/src/tinydisplay/zline.h @@ -2,7 +2,7 @@ int n, dx, dy, sx, pp_inc_1, pp_inc_2; register int a; register PIXEL *pp; -#if defined(INTERP_RGB) || TGL_FEATURE_RENDER_BITS == 24 +#if defined(INTERP_RGB) register unsigned int r, g, b; #endif #ifdef INTERP_RGB @@ -33,27 +33,14 @@ r = p2->r << 8; g = p2->g << 8; b = p2->b << 8; -#elif TGL_FEATURE_RENDER_BITS == 24 - /* for 24 bits, we store the colors in different variables */ - r = p2->r >> 8; - g = p2->g >> 8; - b = p2->b >> 8; #endif #ifdef INTERP_RGB #define RGB(x) x -#if TGL_FEATURE_RENDER_BITS == 24 -#define RGBPIXEL pp[0] = r >> 16, pp[1] = g >> 16, pp[2] = b >> 16 -#else #define RGBPIXEL *pp = RGB_TO_PIXEL(r >> 8,g >> 8,b >> 8) -#endif #else /* INTERP_RGB */ #define RGB(x) -#if TGL_FEATURE_RENDER_BITS == 24 -#define RGBPIXEL pp[0] = r, pp[1] = g, pp[2] = b -#else #define RGBPIXEL *pp = color -#endif #endif /* INTERP_RGB */ #ifdef INTERP_Z diff --git a/panda/src/tinydisplay/ztriangle.c b/panda/src/tinydisplay/ztriangle.c index 0bcc73ef67..80d290d562 100644 --- a/panda/src/tinydisplay/ztriangle.c +++ b/panda/src/tinydisplay/ztriangle.c @@ -1,304 +1,23 @@ #include +#include #include "zbuffer.h" -#define ZCMP(z,zpix) ((z) >= (zpix)) +#define ACMP(a) 1 +#define ZCMP(z,zpix) 1 +#define FNAME(name) name ## _anone_znone +#include "ztriangle_two.h" -void ZB_fillTriangleFlat(ZBuffer *zb, - ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) -{ - int color; +#define ACMP(a) 1 +#define ZCMP(z,zpix) ((zpix) < (z)) +#define FNAME(name) name ## _anone_zless +#include "ztriangle_two.h" -#define INTERP_Z +#define ACMP(a) ((a) > 0x8000) +#define ZCMP(z,zpix) 1 +#define FNAME(name) name ## _abin_znone +#include "ztriangle_two.h" -#define DRAW_INIT() \ -{ \ - color=RGB_TO_PIXEL(p2->r,p2->g,p2->b); \ -} - -#define PUT_PIXEL(_a) \ -{ \ - zz=z >> ZB_POINT_Z_FRAC_BITS; \ - if (ZCMP(zz,pz[_a])) { \ - pp[_a]=color; \ - pz[_a]=zz; \ - } \ - z+=dzdx; \ -} - -#include "ztriangle.h" -} - -/* - * Smooth filled triangle. - * The code below is very tricky :) - */ - -void ZB_fillTriangleSmooth(ZBuffer *zb, - ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) -{ -#define INTERP_Z -#define INTERP_RGB - -#define SAR_RND_TO_ZERO(v,n) (v / (1<> ZB_POINT_Z_FRAC_BITS; \ - if (ZCMP(zz,pz[_a])) { \ - pp[_a] = RGB_TO_PIXEL(or1, og1, ob1);\ - pz[_a]=zz; \ - }\ - z+=dzdx; \ - og1+=dgdx; \ - or1+=drdx; \ - ob1+=dbdx; \ -} - -#include "ztriangle.h" -} - -void ZB_setTexture(ZBuffer *zb,PIXEL *texture) -{ - zb->current_texture=texture; -} - -void ZB_fillTriangleMapping(ZBuffer *zb, - ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) -{ - PIXEL *texture; - -#define INTERP_Z -#define INTERP_ST - -#define DRAW_INIT() \ -{ \ - texture=zb->current_texture; \ -} - -#define PUT_PIXEL(_a) \ -{ \ - zz=z >> ZB_POINT_Z_FRAC_BITS; \ - if (ZCMP(zz,pz[_a])) { \ - pp[_a]=texture[((t & 0x3FC00000) | s) >> 14]; \ - pz[_a]=zz; \ - } \ - z+=dzdx; \ - s+=dsdx; \ - t+=dtdx; \ -} - -#include "ztriangle.h" -} - -/* - * Texture mapping with perspective correction. - * We use the gradient method to make less divisions. - * TODO: pipeline the division - */ -void ZB_fillTriangleMappingPerspective(ZBuffer *zb, - ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) -{ - PIXEL *texture; - float fdzdx,fndzdx,ndszdx,ndtzdx; - -#define INTERP_Z -#define INTERP_STZ - -#define NB_INTERP 8 - -#define DRAW_INIT() \ -{ \ - texture=zb->current_texture;\ - fdzdx=(float)dzdx;\ - fndzdx=NB_INTERP * fdzdx;\ - ndszdx=NB_INTERP * dszdx;\ - ndtzdx=NB_INTERP * dtzdx;\ -} - - -#define PUT_PIXEL(_a) \ -{ \ - zz=z >> ZB_POINT_Z_FRAC_BITS; \ - if (ZCMP(zz,pz[_a])) { \ - pp[_a]=*(PIXEL *)((char *)texture+ \ - (((t & 0x3FC00000) | (s & 0x003FC000)) >> (17 - PSZSH)));\ - pz[_a]=zz; \ - } \ - z+=dzdx; \ - s+=dsdx; \ - t+=dtdx; \ -} - -#define DRAW_LINE() \ -{ \ - register unsigned short *pz; \ - register PIXEL *pp; \ - register unsigned int s,t,z,zz; \ - register int n,dsdx,dtdx; \ - float sz,tz,fz,zinv; \ - n=(x2>>16)-x1; \ - fz=(float)z1;\ - zinv=1.0 / fz;\ - pp=(PIXEL *)((char *)pp1 + x1 * PSZB); \ - pz=pz1+x1; \ - z=z1; \ - sz=sz1;\ - tz=tz1;\ - while (n>=(NB_INTERP-1)) { \ - {\ - float ss,tt;\ - ss=(sz * zinv);\ - tt=(tz * zinv);\ - s=(int) ss;\ - t=(int) tt;\ - dsdx= (int)( (dszdx - ss*fdzdx)*zinv );\ - dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );\ - fz+=fndzdx;\ - zinv=1.0 / fz;\ - }\ - PUT_PIXEL(0); \ - PUT_PIXEL(1); \ - PUT_PIXEL(2); \ - PUT_PIXEL(3); \ - PUT_PIXEL(4); \ - PUT_PIXEL(5); \ - PUT_PIXEL(6); \ - PUT_PIXEL(7); \ - pz+=NB_INTERP; \ - pp=(PIXEL *)((char *)pp + NB_INTERP * PSZB);\ - n-=NB_INTERP; \ - sz+=ndszdx;\ - tz+=ndtzdx;\ - } \ - {\ - float ss,tt;\ - ss=(sz * zinv);\ - tt=(tz * zinv);\ - s=(int) ss;\ - t=(int) tt;\ - dsdx= (int)( (dszdx - ss*fdzdx)*zinv );\ - dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );\ - }\ - while (n>=0) { \ - PUT_PIXEL(0); \ - pz+=1; \ - pp=(PIXEL *)((char *)pp + PSZB);\ - n-=1; \ - } \ -} - -#include "ztriangle.h" -} - -/* - * Smooth filled triangle, with perspective-correct mapping. - */ - -void ZB_fillTriangleMappingSmooth(ZBuffer *zb, - ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) -{ - PIXEL *texture; - float fdzdx,fndzdx,ndszdx,ndtzdx; - -#define INTERP_Z -#define INTERP_STZ -#define INTERP_RGB - -#define SAR_RND_TO_ZERO(v,n) (v / (1<current_texture;\ - fdzdx=(float)dzdx;\ - fndzdx=NB_INTERP * fdzdx;\ - ndszdx=NB_INTERP * dszdx;\ - ndtzdx=NB_INTERP * dtzdx;\ -} - -#define PUT_PIXEL(_a) \ -{ \ - zz=z >> ZB_POINT_Z_FRAC_BITS; \ - if (ZCMP(zz,pz[_a])) { \ - tmp=*(PIXEL *)((char *)texture+ \ - (((t & 0x3FC00000) | (s & 0x003FC000)) >> (17 - PSZSH))); \ - pp[_a] = RGB_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \ - og1 * PIXEL_G(tmp) >> 16, \ - ob1 * PIXEL_B(tmp) >> 16); \ - pz[_a]=zz; \ - }\ - z+=dzdx; \ - og1+=dgdx; \ - or1+=drdx; \ - ob1+=dbdx; \ - s+=dsdx; \ - t+=dtdx; \ -} - -#define DRAW_LINE() \ -{ \ - register unsigned short *pz; \ - register PIXEL *pp; \ - register unsigned int s,t,z,zz; \ - register int n,dsdx,dtdx; \ - register unsigned int or1,og1,ob1; \ - float sz,tz,fz,zinv; \ - n=(x2>>16)-x1; \ - fz=(float)z1;\ - zinv=1.0 / fz;\ - pp=(PIXEL *)((char *)pp1 + x1 * PSZB); \ - pz=pz1+x1; \ - z=z1; \ - sz=sz1;\ - tz=tz1;\ - or1 = r1;\ - og1 = g1;\ - ob1 = b1;\ - while (n>=(NB_INTERP-1)) { \ - {\ - float ss,tt;\ - ss=(sz * zinv);\ - tt=(tz * zinv);\ - s=(int) ss;\ - t=(int) tt;\ - dsdx= (int)( (dszdx - ss*fdzdx)*zinv );\ - dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );\ - fz+=fndzdx;\ - zinv=1.0 / fz;\ - }\ - PUT_PIXEL(0); \ - PUT_PIXEL(1); \ - PUT_PIXEL(2); \ - PUT_PIXEL(3); \ - PUT_PIXEL(4); \ - PUT_PIXEL(5); \ - PUT_PIXEL(6); \ - PUT_PIXEL(7); \ - pz+=NB_INTERP; \ - pp=(PIXEL *)((char *)pp + NB_INTERP * PSZB);\ - n-=NB_INTERP; \ - sz+=ndszdx;\ - tz+=ndtzdx;\ - } \ - {\ - float ss,tt;\ - ss=(sz * zinv);\ - tt=(tz * zinv);\ - s=(int) ss;\ - t=(int) tt;\ - dsdx= (int)( (dszdx - ss*fdzdx)*zinv );\ - dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );\ - }\ - while (n>=0) { \ - PUT_PIXEL(0); \ - pz+=1; \ - pp=(PIXEL *)((char *)pp + PSZB);\ - n-=1; \ - } \ -} - -#include "ztriangle.h" -} +#define ACMP(a) ((a) > 0x8000) +#define ZCMP(z,zpix) ((zpix) < (z)) +#define FNAME(name) name ## _abin_zless +#include "ztriangle_two.h" diff --git a/panda/src/tinydisplay/ztriangle.h b/panda/src/tinydisplay/ztriangle.h index b61426420c..33113c895a 100644 --- a/panda/src/tinydisplay/ztriangle.h +++ b/panda/src/tinydisplay/ztriangle.h @@ -23,6 +23,7 @@ int r1,drdx,drdy,drdl_min,drdl_max; int g1,dgdx,dgdy,dgdl_min,dgdl_max; int b1,dbdx,dbdy,dbdl_min,dbdl_max; + int a1,dadx,dady,dadl_min,dadl_max; #endif #ifdef INTERP_ST int s1,dsdx,dsdy,dsdl_min,dsdl_max; @@ -91,6 +92,11 @@ dbdx = (int) (fdy2 * d1 - fdy1 * d2); dbdy = (int) (fdx1 * d2 - fdx2 * d1); + d1 = p1->a - p0->a; + d2 = p2->a - p0->a; + dadx = (int) (fdy2 * d1 - fdy1 * d2); + dady = (int) (fdx1 * d2 - fdx2 * d1); + #endif #ifdef INTERP_ST @@ -203,6 +209,10 @@ b1=l1->b; dbdl_min=(dbdy + dbdx * dxdy_min); dbdl_max=dbdl_min + dbdx; + + a1=l1->a; + dadl_min=(dady + dadx * dxdy_min); + dadl_max=dadl_min + dadx; #endif #ifdef INTERP_ST s1=l1->s; @@ -250,7 +260,7 @@ register unsigned int z,zz; #endif #ifdef INTERP_RGB - register unsigned int or1,og1,ob1; + register unsigned int or1,og1,ob1,oa1; #endif #ifdef INTERP_ST register unsigned int s,t; @@ -269,6 +279,7 @@ or1 = r1; og1 = g1; ob1 = b1; + oa1 = a1; #endif #ifdef INTERP_ST s=s1; @@ -314,6 +325,7 @@ r1+=drdl_max; g1+=dgdl_max; b1+=dbdl_max; + a1+=dadl_max; #endif #ifdef INTERP_ST s1+=dsdl_max; diff --git a/panda/src/tinydisplay/ztriangle_two.h b/panda/src/tinydisplay/ztriangle_two.h new file mode 100644 index 0000000000..478afbcc1b --- /dev/null +++ b/panda/src/tinydisplay/ztriangle_two.h @@ -0,0 +1,508 @@ +void FNAME(ZB_fillTriangleFlat) (ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + int color; + int oa; + +#define INTERP_Z + +#define DRAW_INIT() \ + { \ + if (!ACMP(p2->a)) { \ + return; \ + } \ + color=RGBA_TO_PIXEL(p2->r,p2->g,p2->b,p2->a); \ + } + +#define PUT_PIXEL(_a) \ + { \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + pp[_a]=color; \ + pz[_a]=zz; \ + } \ + z+=dzdx; \ + } + +#include "ztriangle.h" +} + +/* + * Smooth filled triangle. + * The code below is very tricky :) + */ + +void FNAME(ZB_fillTriangleSmooth) (ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ +#define INTERP_Z +#define INTERP_RGB + +#define DRAW_INIT() \ + { \ + } + +#define PUT_PIXEL(_a) \ + { \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + if (ACMP(oa1)) { \ + pp[_a] = RGBA_TO_PIXEL(or1, og1, ob1, oa1); \ + pz[_a]=zz; \ + } \ + } \ + z+=dzdx; \ + og1+=dgdx; \ + or1+=drdx; \ + ob1+=dbdx; \ + oa1+=dadx; \ + } + +#include "ztriangle.h" +} + +void FNAME(ZB_fillTriangleMapping) (ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + PIXEL *texture; + +#define INTERP_Z +#define INTERP_ST + +#define DRAW_INIT() \ + { \ + texture=zb->current_texture; \ + } + +#define PUT_PIXEL(_a) \ + { \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + tmp=texture[((t & 0x3FC00000) | s) >> 14]; \ + if (ACMP(PIXEL_A(tmp))) { \ + pp[_a]=tmp; \ + pz[_a]=zz; \ + } \ + } \ + z+=dzdx; \ + s+=dsdx; \ + t+=dtdx; \ + } + +#include "ztriangle.h" +} + +void FNAME(ZB_fillTriangleMappingFlat) (ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + PIXEL *texture; + int or, og, ob, oa; + +#define INTERP_Z +#define INTERP_ST + +#define DRAW_INIT() \ + { \ + texture=zb->current_texture; \ + or = p2->r; \ + og = p2->g; \ + ob = p2->b; \ + oa = p2->a; \ + } + +#define PUT_PIXEL(_a) \ + { \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + tmp=texture[((t & 0x3FC00000) | s) >> 14]; \ + int a = oa * PIXEL_A(tmp) >> 16; \ + if (ACMP(a)) { \ + pp[_a] = RGBA_TO_PIXEL(or * PIXEL_R(tmp) >> 16, \ + og * PIXEL_G(tmp) >> 16, \ + ob * PIXEL_B(tmp) >> 16, \ + a); \ + pz[_a]=zz; \ + } \ + } \ + z+=dzdx; \ + s+=dsdx; \ + t+=dtdx; \ + } + +#include "ztriangle.h" +} + +void FNAME(ZB_fillTriangleMappingSmooth) (ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + PIXEL *texture; + +#define INTERP_Z +#define INTERP_ST +#define INTERP_RGB + +#define DRAW_INIT() \ + { \ + texture=zb->current_texture; \ + } + +#define PUT_PIXEL(_a) \ + { \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + tmp=texture[((t & 0x3FC00000) | s) >> 14]; \ + int a = oa1 * PIXEL_A(tmp) >> 16; \ + if (ACMP(a)) { \ + pp[_a] = RGBA_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \ + og1 * PIXEL_G(tmp) >> 16, \ + ob1 * PIXEL_B(tmp) >> 16, \ + a); \ + pz[_a]=zz; \ + } \ + } \ + z+=dzdx; \ + og1+=dgdx; \ + or1+=drdx; \ + ob1+=dbdx; \ + oa1+=dadx; \ + s+=dsdx; \ + t+=dtdx; \ + } + +#include "ztriangle.h" +} + +/* + * Texture mapping with perspective correction. + * We use the gradient method to make less divisions. + * TODO: pipeline the division + */ +void FNAME(ZB_fillTriangleMappingPerspective) (ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + PIXEL *texture; + float fdzdx,fndzdx,ndszdx,ndtzdx; + +#define INTERP_Z +#define INTERP_STZ + +#define NB_INTERP 8 + +#define DRAW_INIT() \ + { \ + texture=zb->current_texture; \ + fdzdx=(float)dzdx; \ + fndzdx=NB_INTERP * fdzdx; \ + ndszdx=NB_INTERP * dszdx; \ + ndtzdx=NB_INTERP * dtzdx; \ + } + + +#define PUT_PIXEL(_a) \ + { \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + tmp = *(PIXEL *)((char *)texture+ \ + (((t & 0x3FC00000) | (s & 0x003FC000)) >> (17 - PSZSH))); \ + if (ACMP(PIXEL_A(tmp))) { \ + pp[_a]=tmp; \ + pz[_a]=zz; \ + } \ + } \ + z+=dzdx; \ + s+=dsdx; \ + t+=dtdx; \ + } + +#define DRAW_LINE() \ + { \ + register unsigned short *pz; \ + register PIXEL *pp; \ + register unsigned int s,t,z,zz; \ + register int n,dsdx,dtdx; \ + float sz,tz,fz,zinv; \ + n=(x2>>16)-x1; \ + fz=(float)z1; \ + zinv=1.0 / fz; \ + pp=(PIXEL *)((char *)pp1 + x1 * PSZB); \ + pz=pz1+x1; \ + z=z1; \ + sz=sz1; \ + tz=tz1; \ + while (n>=(NB_INTERP-1)) { \ + { \ + float ss,tt; \ + ss=(sz * zinv); \ + tt=(tz * zinv); \ + s=(int) ss; \ + t=(int) tt; \ + dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \ + dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \ + fz+=fndzdx; \ + zinv=1.0 / fz; \ + } \ + PUT_PIXEL(0); \ + PUT_PIXEL(1); \ + PUT_PIXEL(2); \ + PUT_PIXEL(3); \ + PUT_PIXEL(4); \ + PUT_PIXEL(5); \ + PUT_PIXEL(6); \ + PUT_PIXEL(7); \ + pz+=NB_INTERP; \ + pp=(PIXEL *)((char *)pp + NB_INTERP * PSZB); \ + n-=NB_INTERP; \ + sz+=ndszdx; \ + tz+=ndtzdx; \ + } \ + { \ + float ss,tt; \ + ss=(sz * zinv); \ + tt=(tz * zinv); \ + s=(int) ss; \ + t=(int) tt; \ + dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \ + dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \ + } \ + while (n>=0) { \ + PUT_PIXEL(0); \ + pz+=1; \ + pp=(PIXEL *)((char *)pp + PSZB); \ + n-=1; \ + } \ + } + +#include "ztriangle.h" +} + +/* + * Flat shaded triangle, with perspective-correct mapping. + */ + +void FNAME(ZB_fillTriangleMappingPerspectiveFlat) (ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + PIXEL *texture; + float fdzdx,fndzdx,ndszdx,ndtzdx; + int or, og, ob, oa; + +#define INTERP_Z +#define INTERP_STZ +#define INTERP_RGB + + +#define DRAW_INIT() \ + { \ + texture=zb->current_texture; \ + fdzdx=(float)dzdx; \ + fndzdx=NB_INTERP * fdzdx; \ + ndszdx=NB_INTERP * dszdx; \ + ndtzdx=NB_INTERP * dtzdx; \ + or = p2->r; \ + og = p2->g; \ + ob = p2->b; \ + oa = p2->a; \ + } + +#define PUT_PIXEL(_a) \ + { \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + tmp=*(PIXEL *)((char *)texture+ \ + (((t & 0x3FC00000) | (s & 0x003FC000)) >> (17 - PSZSH))); \ + int a = oa * PIXEL_A(tmp) >> 16; \ + if (ACMP(a)) { \ + pp[_a] = RGBA_TO_PIXEL(or * PIXEL_R(tmp) >> 16, \ + og * PIXEL_G(tmp) >> 16, \ + ob * PIXEL_B(tmp) >> 16, \ + a); \ + pz[_a]=zz; \ + } \ + } \ + z+=dzdx; \ + s+=dsdx; \ + t+=dtdx; \ + } + +#define DRAW_LINE() \ + { \ + register unsigned short *pz; \ + register PIXEL *pp; \ + register unsigned int s,t,z,zz; \ + register int n,dsdx,dtdx; \ + register unsigned int or1,og1,ob1,oa1; \ + float sz,tz,fz,zinv; \ + n=(x2>>16)-x1; \ + fz=(float)z1; \ + zinv=1.0 / fz; \ + pp=(PIXEL *)((char *)pp1 + x1 * PSZB); \ + pz=pz1+x1; \ + z=z1; \ + sz=sz1; \ + tz=tz1; \ + or1 = r1; \ + og1 = g1; \ + ob1 = b1; \ + oa1 = a1; \ + while (n>=(NB_INTERP-1)) { \ + { \ + float ss,tt; \ + ss=(sz * zinv); \ + tt=(tz * zinv); \ + s=(int) ss; \ + t=(int) tt; \ + dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \ + dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \ + fz+=fndzdx; \ + zinv=1.0 / fz; \ + } \ + PUT_PIXEL(0); \ + PUT_PIXEL(1); \ + PUT_PIXEL(2); \ + PUT_PIXEL(3); \ + PUT_PIXEL(4); \ + PUT_PIXEL(5); \ + PUT_PIXEL(6); \ + PUT_PIXEL(7); \ + pz+=NB_INTERP; \ + pp=(PIXEL *)((char *)pp + NB_INTERP * PSZB); \ + n-=NB_INTERP; \ + sz+=ndszdx; \ + tz+=ndtzdx; \ + } \ + { \ + float ss,tt; \ + ss=(sz * zinv); \ + tt=(tz * zinv); \ + s=(int) ss; \ + t=(int) tt; \ + dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \ + dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \ + } \ + while (n>=0) { \ + PUT_PIXEL(0); \ + pz+=1; \ + pp=(PIXEL *)((char *)pp + PSZB); \ + n-=1; \ + } \ + } + +#include "ztriangle.h" +} + +/* + * Smooth filled triangle, with perspective-correct mapping. + */ + +void FNAME(ZB_fillTriangleMappingPerspectiveSmooth) (ZBuffer *zb, + ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) +{ + PIXEL *texture; + float fdzdx,fndzdx,ndszdx,ndtzdx; + +#define INTERP_Z +#define INTERP_STZ +#define INTERP_RGB + +#define DRAW_INIT() \ + { \ + texture=zb->current_texture; \ + fdzdx=(float)dzdx; \ + fndzdx=NB_INTERP * fdzdx; \ + ndszdx=NB_INTERP * dszdx; \ + ndtzdx=NB_INTERP * dtzdx; \ + } + +#define PUT_PIXEL(_a) \ + { \ + zz=z >> ZB_POINT_Z_FRAC_BITS; \ + if (ZCMP(zz,pz[_a])) { \ + tmp=*(PIXEL *)((char *)texture+ \ + (((t & 0x3FC00000) | (s & 0x003FC000)) >> (17 - PSZSH))); \ + int a = oa1 * PIXEL_A(tmp) >> 16; \ + if (ACMP(a)) { \ + pp[_a] = RGBA_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \ + og1 * PIXEL_G(tmp) >> 16, \ + ob1 * PIXEL_B(tmp) >> 16, \ + a); \ + pz[_a]=zz; \ + } \ + } \ + z+=dzdx; \ + og1+=dgdx; \ + or1+=drdx; \ + ob1+=dbdx; \ + oa1+=dadx; \ + s+=dsdx; \ + t+=dtdx; \ + } + +#define DRAW_LINE() \ + { \ + register unsigned short *pz; \ + register PIXEL *pp; \ + register unsigned int s,t,z,zz; \ + register int n,dsdx,dtdx; \ + register unsigned int or1,og1,ob1,oa1; \ + float sz,tz,fz,zinv; \ + n=(x2>>16)-x1; \ + fz=(float)z1; \ + zinv=1.0 / fz; \ + pp=(PIXEL *)((char *)pp1 + x1 * PSZB); \ + pz=pz1+x1; \ + z=z1; \ + sz=sz1; \ + tz=tz1; \ + or1 = r1; \ + og1 = g1; \ + ob1 = b1; \ + oa1 = a1; \ + while (n>=(NB_INTERP-1)) { \ + { \ + float ss,tt; \ + ss=(sz * zinv); \ + tt=(tz * zinv); \ + s=(int) ss; \ + t=(int) tt; \ + dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \ + dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \ + fz+=fndzdx; \ + zinv=1.0 / fz; \ + } \ + PUT_PIXEL(0); \ + PUT_PIXEL(1); \ + PUT_PIXEL(2); \ + PUT_PIXEL(3); \ + PUT_PIXEL(4); \ + PUT_PIXEL(5); \ + PUT_PIXEL(6); \ + PUT_PIXEL(7); \ + pz+=NB_INTERP; \ + pp=(PIXEL *)((char *)pp + NB_INTERP * PSZB); \ + n-=NB_INTERP; \ + sz+=ndszdx; \ + tz+=ndtzdx; \ + } \ + { \ + float ss,tt; \ + ss=(sz * zinv); \ + tt=(tz * zinv); \ + s=(int) ss; \ + t=(int) tt; \ + dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \ + dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \ + } \ + while (n>=0) { \ + PUT_PIXEL(0); \ + pz+=1; \ + pp=(PIXEL *)((char *)pp + PSZB); \ + n-=1; \ + } \ + } + +#include "ztriangle.h" +} + +#undef ACMP +#undef ZCMP +#undef FNAME