mesa: Delete libmesa_classic

We no longer have any classic drivers, so we no longer need
libmesa_classic

Reviewed-by: Emma Anholt <emma@anholt.net>
Acked-by: Jason Ekstrand <jason@jlekstrand.net>
Acked-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10153>
This commit is contained in:
Dylan Baker 2021-08-05 10:48:28 -07:00 committed by Marge Bot
parent bc2d3e7b5f
commit e030d5ba8a
145 changed files with 0 additions and 54080 deletions

View File

@ -1,312 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/accum.h"
#include "main/arrayobj.h"
#include "main/context.h"
#include "main/draw.h"
#include "main/formatquery.h"
#include "main/framebuffer.h"
#include "main/mipmap.h"
#include "main/queryobj.h"
#include "main/readpix.h"
#include "main/rastpos.h"
#include "main/renderbuffer.h"
#include "main/shaderobj.h"
#include "main/texcompress.h"
#include "main/texformat.h"
#include "main/texgetimage.h"
#include "main/teximage.h"
#include "main/texobj.h"
#include "main/texstorage.h"
#include "main/texstore.h"
#include "main/bufferobj.h"
#include "main/fbobject.h"
#include "main/samplerobj.h"
#include "main/syncobj.h"
#include "main/barrier.h"
#include "main/transformfeedback.h"
#include "main/externalobjects.h"
#include "program/program.h"
#include "tnl/tnl.h"
#include "swrast/swrast.h"
#include "swrast/s_renderbuffer.h"
#include "driverfuncs.h"
#include "meta.h"
/**
* Plug in default functions for all pointers in the dd_function_table
* structure.
* Device drivers should call this function and then plug in any
* functions which it wants to override.
* Some functions (pointers) MUST be implemented by all drivers (REQUIRED).
*
* \param table the dd_function_table to initialize
*/
void
_mesa_init_driver_functions(struct dd_function_table *driver)
{
memset(driver, 0, sizeof(*driver));
driver->GetString = NULL; /* REQUIRED! */
driver->UpdateState = NULL; /* REQUIRED! */
driver->Finish = NULL;
driver->Flush = NULL;
/* framebuffer/image functions */
driver->Clear = _swrast_Clear;
driver->RasterPos = _mesa_RasterPos;
driver->DrawPixels = _swrast_DrawPixels;
driver->ReadPixels = _mesa_readpixels;
driver->CopyPixels = _swrast_CopyPixels;
driver->Bitmap = _swrast_Bitmap;
/* Texture functions */
driver->ChooseTextureFormat = _mesa_choose_tex_format;
driver->QueryInternalFormat = _mesa_query_internal_format_default;
driver->TexImage = _mesa_store_teximage;
driver->TexSubImage = _mesa_store_texsubimage;
driver->GetTexSubImage = _mesa_meta_GetTexSubImage;
driver->ClearTexSubImage = _mesa_meta_ClearTexSubImage;
driver->CopyTexSubImage = _mesa_meta_CopyTexSubImage;
driver->GenerateMipmap = _mesa_meta_GenerateMipmap;
driver->TestProxyTexImage = _mesa_test_proxy_teximage;
driver->CompressedTexImage = _mesa_store_compressed_teximage;
driver->CompressedTexSubImage = _mesa_store_compressed_texsubimage;
driver->BindTexture = NULL;
driver->NewTextureObject = _mesa_new_texture_object;
driver->DeleteTexture = _mesa_delete_texture_object;
driver->NewTextureImage = _swrast_new_texture_image;
driver->DeleteTextureImage = _swrast_delete_texture_image;
driver->AllocTextureImageBuffer = _swrast_alloc_texture_image_buffer;
driver->FreeTextureImageBuffer = _swrast_free_texture_image_buffer;
driver->MapTextureImage = _swrast_map_teximage;
driver->UnmapTextureImage = _swrast_unmap_teximage;
driver->DrawTex = _mesa_meta_DrawTex;
/* Vertex/fragment programs */
driver->NewProgram = _mesa_new_program;
driver->DeleteProgram = _mesa_delete_program;
/* ATI_fragment_shader */
driver->NewATIfs = NULL;
/* Draw functions */
driver->Draw = NULL;
driver->DrawGallium = _mesa_draw_gallium_fallback;
driver->DrawGalliumMultiMode = _mesa_draw_gallium_multimode_fallback;
driver->DrawIndirect = NULL;
driver->DrawTransformFeedback = NULL;
/* simple state commands */
driver->AlphaFunc = NULL;
driver->BlendColor = NULL;
driver->BlendEquationSeparate = NULL;
driver->BlendFuncSeparate = NULL;
driver->ClipPlane = NULL;
driver->ColorMask = NULL;
driver->ColorMaterial = NULL;
driver->CullFace = NULL;
driver->DrawBuffer = NULL;
driver->FrontFace = NULL;
driver->DepthFunc = NULL;
driver->DepthMask = NULL;
driver->DepthRange = NULL;
driver->Enable = NULL;
driver->Fogfv = NULL;
driver->Lightfv = NULL;
driver->LightModelfv = NULL;
driver->LineStipple = NULL;
driver->LineWidth = NULL;
driver->LogicOpcode = NULL;
driver->PointParameterfv = NULL;
driver->PointSize = NULL;
driver->PolygonMode = NULL;
driver->PolygonOffset = NULL;
driver->PolygonStipple = NULL;
driver->ReadBuffer = NULL;
driver->RenderMode = NULL;
driver->Scissor = NULL;
driver->ShadeModel = NULL;
driver->StencilFuncSeparate = NULL;
driver->StencilOpSeparate = NULL;
driver->StencilMaskSeparate = NULL;
driver->TexGen = NULL;
driver->TexEnv = NULL;
driver->TexParameter = NULL;
driver->Viewport = NULL;
/* buffer objects */
_mesa_init_buffer_object_functions(driver);
/* query objects */
_mesa_init_query_object_functions(driver);
_mesa_init_sync_object_functions(driver);
/* memory objects */
_mesa_init_memory_object_functions(driver);
driver->NewFramebuffer = _mesa_new_framebuffer;
driver->NewRenderbuffer = _swrast_new_soft_renderbuffer;
driver->MapRenderbuffer = _swrast_map_soft_renderbuffer;
driver->UnmapRenderbuffer = _swrast_unmap_soft_renderbuffer;
driver->RenderTexture = _swrast_render_texture;
driver->FinishRenderTexture = _swrast_finish_render_texture;
driver->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw;
driver->ValidateFramebuffer = _mesa_validate_framebuffer;
driver->BlitFramebuffer = _swrast_BlitFramebuffer;
driver->DiscardFramebuffer = NULL;
_mesa_init_barrier_functions(driver);
_mesa_init_shader_object_functions(driver);
_mesa_init_transform_feedback_functions(driver);
_mesa_init_sampler_object_functions(driver);
/* T&L stuff */
driver->CurrentExecPrimitive = 0;
driver->CurrentSavePrimitive = 0;
driver->NeedFlush = 0;
driver->SaveNeedFlush = 0;
driver->ProgramStringNotify = _tnl_program_string;
driver->LightingSpaceChange = NULL;
/* GL_ARB_texture_storage */
driver->AllocTextureStorage = _mesa_AllocTextureStorage_sw;
/* GL_ARB_texture_view */
driver->TextureView = NULL;
/* GL_ARB_texture_multisample */
driver->GetSamplePosition = NULL;
/* Multithreading */
driver->SetBackgroundContext = NULL;
}
/**
* Call the ctx->Driver.* state functions with current values to initialize
* driver state.
* Only the Intel drivers use this so far.
*/
void
_mesa_init_driver_state(struct gl_context *ctx)
{
ctx->Driver.AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);
ctx->Driver.BlendColor(ctx, ctx->Color.BlendColor);
ctx->Driver.BlendEquationSeparate(ctx,
ctx->Color.Blend[0].EquationRGB,
ctx->Color.Blend[0].EquationA);
ctx->Driver.BlendFuncSeparate(ctx,
ctx->Color.Blend[0].SrcRGB,
ctx->Color.Blend[0].DstRGB,
ctx->Color.Blend[0].SrcA,
ctx->Color.Blend[0].DstA);
ctx->Driver.ColorMask(ctx,
GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0),
GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1),
GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2),
GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3));
ctx->Driver.CullFace(ctx, ctx->Polygon.CullFaceMode);
ctx->Driver.DepthFunc(ctx, ctx->Depth.Func);
ctx->Driver.DepthMask(ctx, ctx->Depth.Mask);
ctx->Driver.Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled);
ctx->Driver.Enable(ctx, GL_BLEND, ctx->Color.BlendEnabled);
ctx->Driver.Enable(ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled);
ctx->Driver.Enable(ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled);
ctx->Driver.Enable(ctx, GL_CULL_FACE, ctx->Polygon.CullFlag);
ctx->Driver.Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test);
ctx->Driver.Enable(ctx, GL_DITHER, ctx->Color.DitherFlag);
ctx->Driver.Enable(ctx, GL_FOG, ctx->Fog.Enabled);
ctx->Driver.Enable(ctx, GL_LIGHTING, ctx->Light.Enabled);
ctx->Driver.Enable(ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag);
ctx->Driver.Enable(ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag);
ctx->Driver.Enable(ctx, GL_SCISSOR_TEST, ctx->Scissor.EnableFlags);
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
ctx->Driver.Enable(ctx, GL_TEXTURE_1D, GL_FALSE);
ctx->Driver.Enable(ctx, GL_TEXTURE_2D, GL_FALSE);
ctx->Driver.Enable(ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE);
ctx->Driver.Enable(ctx, GL_TEXTURE_3D, GL_FALSE);
ctx->Driver.Enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
ctx->Driver.Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color);
{
GLfloat mode = (GLfloat) ctx->Fog.Mode;
ctx->Driver.Fogfv(ctx, GL_FOG_MODE, &mode);
}
ctx->Driver.Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density);
ctx->Driver.Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start);
ctx->Driver.Fogfv(ctx, GL_FOG_END, &ctx->Fog.End);
ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
{
GLfloat f = (GLfloat) ctx->Light.Model.ColorControl;
ctx->Driver.LightModelfv(ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f);
}
ctx->Driver.LineWidth(ctx, ctx->Line.Width);
ctx->Driver.LogicOpcode(ctx, ctx->Color._LogicOp);
ctx->Driver.PointSize(ctx, ctx->Point.Size);
ctx->Driver.PolygonStipple(ctx, (const GLubyte *) ctx->PolygonStipple);
ctx->Driver.Scissor(ctx);
ctx->Driver.ShadeModel(ctx, ctx->Light.ShadeModel);
ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
ctx->Stencil.Function[0],
ctx->Stencil.Ref[0],
ctx->Stencil.ValueMask[0]);
ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
ctx->Stencil.Function[1],
ctx->Stencil.Ref[1],
ctx->Stencil.ValueMask[1]);
ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT, ctx->Stencil.WriteMask[0]);
ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, ctx->Stencil.WriteMask[1]);
ctx->Driver.StencilOpSeparate(ctx, GL_FRONT,
ctx->Stencil.FailFunc[0],
ctx->Stencil.ZFailFunc[0],
ctx->Stencil.ZPassFunc[0]);
ctx->Driver.StencilOpSeparate(ctx, GL_BACK,
ctx->Stencil.FailFunc[1],
ctx->Stencil.ZFailFunc[1],
ctx->Stencil.ZPassFunc[1]);
ctx->Driver.DrawBuffer(ctx);
}

View File

@ -1,44 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef DRIVERFUNCS_H
#define DRIVERFUNCS_H
#ifdef __cplusplus
extern "C" {
#endif
extern void
_mesa_init_driver_functions(struct dd_function_table *driver);
extern void
_mesa_init_driver_state(struct gl_context *ctx);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,573 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef META_H
#define META_H
#include "main/mtypes.h"
/**
* \name Flags for meta operations
* \{
*
* These flags are passed to _mesa_meta_begin().
*/
#define MESA_META_ALL ~0x0
#define MESA_META_ALPHA_TEST 0x1
#define MESA_META_BLEND 0x2 /**< includes logicop */
#define MESA_META_COLOR_MASK 0x4
#define MESA_META_DEPTH_TEST 0x8
#define MESA_META_FOG 0x10
#define MESA_META_PIXEL_STORE 0x20
#define MESA_META_PIXEL_TRANSFER 0x40
#define MESA_META_RASTERIZATION 0x80
#define MESA_META_SCISSOR 0x100
#define MESA_META_SHADER 0x200
#define MESA_META_STENCIL_TEST 0x400
#define MESA_META_TRANSFORM 0x800 /**< modelview/projection matrix state */
#define MESA_META_TEXTURE 0x1000
#define MESA_META_VERTEX 0x2000
#define MESA_META_VIEWPORT 0x4000
#define MESA_META_CLAMP_FRAGMENT_COLOR 0x8000
#define MESA_META_CLAMP_VERTEX_COLOR 0x10000
#define MESA_META_CONDITIONAL_RENDER 0x20000
#define MESA_META_CLIP 0x40000
#define MESA_META_SELECT_FEEDBACK 0x80000
#define MESA_META_MULTISAMPLE 0x100000
#define MESA_META_FRAMEBUFFER_SRGB 0x200000
#define MESA_META_OCCLUSION_QUERY 0x400000
#define MESA_META_DRAW_BUFFERS 0x800000
#define MESA_META_DITHER 0x1000000
/**\}*/
/**
* State which we may save/restore across meta ops.
* XXX this may be incomplete...
*/
struct save_state
{
GLbitfield SavedState; /**< bitmask of MESA_META_* flags */
/* Always saved/restored with meta. */
gl_api API;
uint8_t ExtensionsVersion;
/** MESA_META_CLEAR (and others?) */
struct gl_query_object *CurrentOcclusionObject;
/** MESA_META_ALPHA_TEST */
GLboolean AlphaEnabled;
GLenum AlphaFunc;
GLclampf AlphaRef;
/** MESA_META_BLEND */
GLbitfield BlendEnabled;
GLboolean ColorLogicOpEnabled;
/** MESA_META_DITHER */
GLboolean DitherFlag;
/** MESA_META_COLOR_MASK */
GLbitfield ColorMask;
/** MESA_META_DEPTH_TEST */
struct gl_depthbuffer_attrib Depth;
/** MESA_META_FOG */
GLboolean Fog;
/** MESA_META_PIXEL_STORE */
struct gl_pixelstore_attrib Pack, Unpack;
/** MESA_META_PIXEL_TRANSFER */
GLfloat RedBias, RedScale;
GLfloat GreenBias, GreenScale;
GLfloat BlueBias, BlueScale;
GLfloat AlphaBias, AlphaScale;
GLfloat DepthBias, DepthScale;
GLboolean MapColorFlag;
/** MESA_META_RASTERIZATION */
GLenum FrontPolygonMode, BackPolygonMode;
GLboolean PolygonOffset;
GLboolean PolygonSmooth;
GLboolean PolygonStipple;
GLboolean PolygonCull;
/** MESA_META_SCISSOR */
struct gl_scissor_attrib Scissor;
/** MESA_META_SHADER */
GLboolean VertexProgramEnabled;
struct gl_program *VertexProgram;
GLboolean FragmentProgramEnabled;
struct gl_program *FragmentProgram;
GLboolean ATIFragmentShaderEnabled;
struct gl_program *Program[MESA_SHADER_STAGES];
struct gl_shader_program *ActiveShader;
struct gl_pipeline_object *Pipeline;
/** MESA_META_STENCIL_TEST */
struct gl_stencil_attrib Stencil;
/** MESA_META_TRANSFORM */
GLfloat ModelviewMatrix[16];
GLfloat ProjectionMatrix[16];
GLfloat TextureMatrix[16];
/** GL_ARB_clip_control */
GLenum ClipOrigin; /**< GL_LOWER_LEFT or GL_UPPER_LEFT */
GLenum ClipDepthMode; /**< GL_NEGATIVE_ONE_TO_ONE or GL_ZERO_TO_ONE */
/** MESA_META_CLIP */
GLbitfield ClipPlanesEnabled;
/** MESA_META_TEXTURE */
GLuint ActiveUnit;
/** for unit[0] only */
struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS];
/** mask of TEXTURE_2D_BIT, etc */
GLbitfield TexEnabled[MAX_TEXTURE_UNITS];
GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS];
GLuint EnvMode; /* unit[0] only */
/** MESA_META_VERTEX */
struct gl_vertex_array_object *VAO;
/** MESA_META_VIEWPORT */
GLfloat ViewportX, ViewportY, ViewportW, ViewportH;
GLclampf DepthNear, DepthFar;
/** MESA_META_CLAMP_FRAGMENT_COLOR */
GLenum ClampFragmentColor;
/** MESA_META_CLAMP_VERTEX_COLOR */
GLenum ClampVertexColor;
/** MESA_META_CONDITIONAL_RENDER */
struct gl_query_object *CondRenderQuery;
GLenum CondRenderMode;
/** MESA_META_SELECT_FEEDBACK */
GLenum RenderMode;
struct gl_selection Select;
struct gl_feedback Feedback;
/** MESA_META_MULTISAMPLE */
struct gl_multisample_attrib Multisample;
/** MESA_META_FRAMEBUFFER_SRGB */
GLboolean sRGBEnabled;
/** Miscellaneous (always disabled) */
GLboolean Lighting;
GLboolean RasterDiscard;
GLboolean TransformFeedbackNeedsResume;
struct gl_framebuffer *DrawBuffer;
struct gl_framebuffer *ReadBuffer;
/** MESA_META_DRAW_BUFFERS */
GLenum16 ColorDrawBuffers[MAX_DRAW_BUFFERS];
};
/**
* Temporary texture used for glBlitFramebuffer, glDrawPixels, etc.
* This is currently shared by all the meta ops. But we could create a
* separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc.
*/
struct temp_texture
{
struct gl_texture_object *tex_obj;
GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */
GLsizei MinSize; /**< Min texture size to allocate */
GLsizei MaxSize; /**< Max possible texture size */
GLboolean NPOT; /**< Non-power of two size OK? */
GLsizei Width, Height; /**< Current texture size */
GLenum IntFormat;
GLfloat Sright, Ttop; /**< right, top texcoords */
};
/**
* State for GLSL texture sampler which is used to generate fragment
* shader in _mesa_meta_generate_mipmap().
*/
struct blit_shader {
const char *type;
const char *func;
const char *texcoords;
struct gl_shader_program *shader_prog;
};
/**
* Table of all sampler types and shaders for accessing them.
*/
struct blit_shader_table {
struct blit_shader sampler_1d;
struct blit_shader sampler_2d;
struct blit_shader sampler_3d;
struct blit_shader sampler_rect;
struct blit_shader sampler_cubemap;
struct blit_shader sampler_1d_array;
struct blit_shader sampler_2d_array;
struct blit_shader sampler_cubemap_array;
};
/**
* State for glBlitFramebufer()
*/
struct blit_state
{
GLuint VAO;
struct gl_buffer_object *buf_obj;
struct blit_shader_table shaders_with_depth;
struct blit_shader_table shaders_without_depth;
struct temp_texture depthTex;
bool no_ctsi_fallback;
};
struct fb_tex_blit_state
{
GLint baseLevelSave, maxLevelSave;
struct gl_sampler_object *samp_obj;
struct gl_sampler_object *samp_obj_save;
struct gl_texture_object *tex_obj;
struct gl_texture_object *temp_tex_obj;
GLuint stencilSamplingSave;
};
/**
* State for glClear()
*/
struct clear_state
{
GLuint VAO;
struct gl_buffer_object *buf_obj;
struct gl_shader_program *ShaderProg;
};
/**
* State for glCopyPixels()
*/
struct copypix_state
{
GLuint VAO;
struct gl_buffer_object *buf_obj;
};
/**
* State for glDrawPixels()
*/
struct drawpix_state
{
GLuint VAO;
struct gl_buffer_object *buf_obj;
GLuint StencilFP; /**< Fragment program for drawing stencil images */
GLuint DepthFP; /**< Fragment program for drawing depth images */
};
/**
* State for glBitmap()
*/
struct bitmap_state
{
GLuint VAO;
struct gl_buffer_object *buf_obj;
struct temp_texture Tex; /**< separate texture from other meta ops */
};
/**
* State for _mesa_meta_generate_mipmap()
*/
struct gen_mipmap_state
{
GLuint VAO;
struct gl_buffer_object *buf_obj;
struct gl_framebuffer *fb;
struct gl_sampler_object *samp_obj;
struct blit_shader_table shaders;
};
/**
* One of the FBO states for decompress_state. There will be one for each
* required renderbuffer format.
*/
struct decompress_fbo_state
{
struct gl_renderbuffer *rb;
struct gl_framebuffer *fb;
GLint Width, Height;
};
/**
* State for texture decompression
*/
struct decompress_state
{
GLuint VAO;
struct decompress_fbo_state byteFBO, floatFBO;
struct gl_buffer_object *buf_obj;
struct gl_sampler_object *samp_obj;
struct blit_shader_table shaders;
};
/**
* State for glDrawTex()
*/
struct drawtex_state
{
GLuint VAO;
struct gl_buffer_object *buf_obj;
};
#define MAX_META_OPS_DEPTH 8
/**
* All per-context meta state.
*/
struct gl_meta_state
{
/** Stack of state saved during meta-ops */
struct save_state Save[MAX_META_OPS_DEPTH];
/** Save stack depth */
GLuint SaveStackDepth;
struct temp_texture TempTex;
struct blit_state Blit; /**< For _mesa_meta_BlitFramebuffer() */
struct clear_state Clear; /**< For _mesa_meta_Clear() */
struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */
struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */
struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */
struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */
struct decompress_state Decompress; /**< For texture decompression */
struct drawtex_state DrawTex; /**< For _mesa_meta_DrawTex() */
};
struct vertex {
GLfloat x, y, z, tex[4];
GLfloat r, g, b, a;
};
extern void
_mesa_meta_init(struct gl_context *ctx);
extern void
_mesa_meta_free(struct gl_context *ctx);
extern void
_mesa_meta_begin(struct gl_context *ctx, GLbitfield state);
extern void
_mesa_meta_end(struct gl_context *ctx);
static inline bool
_mesa_meta_in_progress(struct gl_context *ctx)
{
return ctx->Meta->SaveStackDepth != 0;
}
extern void
_mesa_meta_fb_tex_blit_begin(struct gl_context *ctx,
struct fb_tex_blit_state *blit);
extern void
_mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target,
struct fb_tex_blit_state *blit);
extern GLbitfield
_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
const struct gl_framebuffer *readFb,
const struct gl_framebuffer *drawFb,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
extern void
_mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx,
struct gl_framebuffer *readFb,
struct gl_framebuffer *drawFb,
GLint srcX0, GLint srcY0,
GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
extern void
_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers);
extern void
_mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers);
extern void
_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty, GLenum type);
extern void
_mesa_meta_DrawPixels(struct gl_context *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels);
extern void
_mesa_meta_Bitmap(struct gl_context *ctx,
GLint x, GLint y, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap);
extern void
_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj);
extern void
_mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
struct gl_texture_image *texImage,
GLint xoffset, GLint yoffset, GLint slice,
struct gl_renderbuffer *rb,
GLint x, GLint y,
GLsizei width, GLsizei height);
extern void
_mesa_meta_ClearTexSubImage(struct gl_context *ctx,
struct gl_texture_image *texImage,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
const GLvoid *clearValue);
extern void
_mesa_meta_GetTexSubImage(struct gl_context *ctx,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, GLvoid *pixels,
struct gl_texture_image *texImage);
extern void
_mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
GLfloat width, GLfloat height);
/* meta-internal functions */
void
_mesa_meta_drawbuffers_from_bitfield(GLbitfield bits);
void
_mesa_meta_link_program_with_debug(struct gl_context *ctx,
struct gl_shader_program *sh_prog);
void
_mesa_meta_compile_and_link_program(struct gl_context *ctx,
const char *vs_source,
const char *fs_source,
const char *name,
struct gl_shader_program **sh_prog_ptr);
extern void
_mesa_meta_use_program(struct gl_context *ctx,
struct gl_shader_program *sh_prog);
GLboolean
_mesa_meta_alloc_texture(struct temp_texture *tex,
GLsizei width, GLsizei height, GLenum intFormat);
void
_mesa_meta_setup_texture_coords(GLenum faceTarget,
GLint slice,
GLint xoffset,
GLint yoffset,
GLint width,
GLint height,
GLint total_width,
GLint total_height,
GLint total_depth,
GLfloat coords0[4],
GLfloat coords1[4],
GLfloat coords2[4],
GLfloat coords3[4]);
struct temp_texture *
_mesa_meta_get_temp_texture(struct gl_context *ctx);
struct temp_texture *
_mesa_meta_get_temp_depth_texture(struct gl_context *ctx);
void
_mesa_meta_setup_vertex_objects(struct gl_context *ctx,
GLuint *VAO, struct gl_buffer_object **buf_obj,
bool use_generic_attributes,
unsigned vertex_size, unsigned texcoord_size,
unsigned color_size);
void
_mesa_meta_setup_ff_tnl_for_blit(struct gl_context *ctx,
GLuint *VAO, struct gl_buffer_object **buf_obj,
unsigned texcoord_size);
void
_mesa_meta_setup_drawpix_texture(struct gl_context *ctx,
struct temp_texture *tex,
GLboolean newTex,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels);
void
_mesa_meta_setup_copypix_texture(struct gl_context *ctx,
struct temp_texture *tex,
GLint srcX, GLint srcY,
GLsizei width, GLsizei height,
GLenum intFormat,
GLenum filter);
void
_mesa_meta_setup_blit_shader(struct gl_context *ctx,
GLenum target,
bool do_depth,
struct blit_shader_table *table);
void
_mesa_meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit);
void
_mesa_meta_blit_shader_table_cleanup(struct gl_context *ctx,
struct blit_shader_table *table);
void
_mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
struct gen_mipmap_state *mipmap);
void
_mesa_meta_framebuffer_texture_image(struct gl_context *ctx,
struct gl_framebuffer *fb,
GLenum attachment,
struct gl_texture_image *texImage,
GLuint layer);
#endif /* META_H */

View File

@ -1,543 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/mtypes.h"
#include "main/arbprogram.h"
#include "main/arrayobj.h"
#include "main/blend.h"
#include "main/depth.h"
#include "main/enable.h"
#include "main/enums.h"
#include "main/fbobject.h"
#include "main/image.h"
#include "main/macros.h"
#include "main/matrix.h"
#include "main/readpix.h"
#include "main/scissor.h"
#include "main/shaderapi.h"
#include "main/texobj.h"
#include "main/texenv.h"
#include "main/teximage.h"
#include "main/texparam.h"
#include "main/uniforms.h"
#include "main/varray.h"
#include "main/viewport.h"
#include "swrast/swrast.h"
#include "drivers/common/meta.h"
static struct gl_texture_object *
texture_object_from_renderbuffer(struct gl_context *, struct gl_renderbuffer *);
static struct gl_sampler_object *
setup_sampler(struct gl_context *, struct gl_texture_object *, GLenum target,
GLenum filter, GLuint srcLevel);
/** Return offset in bytes of the field within a vertex struct */
#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
static void
setup_glsl_blit_framebuffer(struct gl_context *ctx,
struct blit_state *blit,
const struct gl_framebuffer *drawFb,
struct gl_renderbuffer *src_rb,
GLenum target,
bool do_depth)
{
const unsigned texcoord_size = 2 + (src_rb->Depth > 1 ? 1 : 0);
/* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */
assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D);
_mesa_meta_setup_vertex_objects(ctx, &blit->VAO, &blit->buf_obj, true,
2, texcoord_size, 0);
_mesa_meta_setup_blit_shader(ctx, target, do_depth,
do_depth ? &blit->shaders_with_depth
: &blit->shaders_without_depth);
}
/**
* Try to do a color or depth glBlitFramebuffer using texturing.
*
* We can do this when the src renderbuffer is actually a texture, or when the
* driver exposes BindRenderbufferTexImage().
*/
static bool
blitframebuffer_texture(struct gl_context *ctx,
const struct gl_framebuffer *readFb,
const struct gl_framebuffer *drawFb,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLenum filter, GLint flipX, GLint flipY,
GLboolean glsl_version, GLboolean do_depth)
{
int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex;
const struct gl_renderbuffer_attachment *readAtt =
&readFb->Attachment[att_index];
struct blit_state *blit = &ctx->Meta->Blit;
struct fb_tex_blit_state fb_tex_blit;
const GLint dstX = MIN2(dstX0, dstX1);
const GLint dstY = MIN2(dstY0, dstY1);
const GLint dstW = abs(dstX1 - dstX0);
const GLint dstH = abs(dstY1 - dstY0);
const int srcW = abs(srcX1 - srcX0);
const int srcH = abs(srcY1 - srcY0);
struct gl_texture_object *texObj;
GLuint srcLevel;
GLenum target;
struct gl_renderbuffer *rb = readAtt->Renderbuffer;
struct temp_texture *meta_temp_texture;
assert(rb->NumSamples == 0);
_mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit);
if (readAtt->Texture &&
(readAtt->Texture->Target == GL_TEXTURE_2D ||
readAtt->Texture->Target == GL_TEXTURE_RECTANGLE)) {
/* If there's a texture attached of a type we can handle, then just use
* it directly.
*/
srcLevel = readAtt->TextureLevel;
texObj = readAtt->Texture;
} else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) {
texObj = texture_object_from_renderbuffer(ctx, rb);
if (texObj == NULL)
return false;
fb_tex_blit.temp_tex_obj = texObj;
srcLevel = 0;
if (_mesa_is_winsys_fbo(readFb)) {
GLint temp = srcY0;
srcY0 = rb->Height - srcY1;
srcY1 = rb->Height - temp;
flipY = -flipY;
}
} else {
GLenum tex_base_format;
/* Fall back to doing a CopyTexSubImage to get the destination
* renderbuffer into a texture.
*/
if (ctx->Meta->Blit.no_ctsi_fallback)
return false;
if (do_depth) {
meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx);
tex_base_format = GL_DEPTH_COMPONENT;
} else {
meta_temp_texture = _mesa_meta_get_temp_texture(ctx);
tex_base_format =
_mesa_base_tex_format(ctx, rb->InternalFormat);
}
srcLevel = 0;
texObj = meta_temp_texture->tex_obj;
if (texObj == NULL) {
return false;
}
_mesa_meta_setup_copypix_texture(ctx, meta_temp_texture,
srcX0, srcY0,
srcW, srcH,
tex_base_format,
filter);
assert(texObj->Target == meta_temp_texture->Target);
srcX0 = 0;
srcY0 = 0;
srcX1 = srcW;
srcY1 = srcH;
}
target = texObj->Target;
fb_tex_blit.tex_obj = texObj;
fb_tex_blit.baseLevelSave = texObj->Attrib.BaseLevel;
fb_tex_blit.maxLevelSave = texObj->Attrib.MaxLevel;
fb_tex_blit.stencilSamplingSave = texObj->StencilSampling;
if (glsl_version) {
setup_glsl_blit_framebuffer(ctx, blit, drawFb, rb, target, do_depth);
}
else {
_mesa_meta_setup_ff_tnl_for_blit(ctx,
&ctx->Meta->Blit.VAO,
&ctx->Meta->Blit.buf_obj,
2);
}
/*
printf("Blit from texture!\n");
printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt);
printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture);
*/
fb_tex_blit.samp_obj = setup_sampler(ctx, texObj, target, filter, srcLevel);
if (ctx->Extensions.EXT_texture_sRGB_decode) {
/* The GL 4.4 spec, section 18.3.1 ("Blitting Pixel Rectangles") says:
*
* "When values are taken from the read buffer, if FRAMEBUFFER_SRGB
* is enabled and the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING
* for the framebuffer attachment corresponding to the read buffer
* is SRGB (see section 9.2.3), the red, green, and blue components
* are converted from the non-linear sRGB color space according to
* equation 3.24.
*
* When values are written to the draw buffers, blit operations
* bypass most of the fragment pipeline. The only fragment
* operations which affect a blit are the pixel ownership test,
* the scissor test, and sRGB conversion (see section 17.3.9)."
*
* ES 3.0 contains nearly the exact same text, but omits the part
* about GL_FRAMEBUFFER_SRGB as that doesn't exist in ES. Mesa
* defaults it to on for ES contexts, so we can safely check it.
*/
const bool decode =
ctx->Color.sRGBEnabled && _mesa_is_format_srgb(rb->Format);
_mesa_set_sampler_srgb_decode(ctx, fb_tex_blit.samp_obj,
decode ? GL_DECODE_EXT
: GL_SKIP_DECODE_EXT);
}
if (!glsl_version) {
_mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
_mesa_set_enable(ctx, target, GL_TRUE);
}
/* Prepare vertex data (the VBO was previously created and bound) */
{
struct vertex verts[4];
GLfloat s0, t0, s1, t1;
if (target == GL_TEXTURE_2D) {
const struct gl_texture_image *texImage
= _mesa_select_tex_image(texObj, target, srcLevel);
s0 = srcX0 / (float) texImage->Width;
s1 = srcX1 / (float) texImage->Width;
t0 = srcY0 / (float) texImage->Height;
t1 = srcY1 / (float) texImage->Height;
}
else {
assert(target == GL_TEXTURE_RECTANGLE_ARB);
s0 = (float) srcX0;
s1 = (float) srcX1;
t0 = (float) srcY0;
t1 = (float) srcY1;
}
/* Silence valgrind warnings about reading uninitialized stack. */
memset(verts, 0, sizeof(verts));
/* setup vertex positions */
verts[0].x = -1.0F * flipX;
verts[0].y = -1.0F * flipY;
verts[1].x = 1.0F * flipX;
verts[1].y = -1.0F * flipY;
verts[2].x = 1.0F * flipX;
verts[2].y = 1.0F * flipY;
verts[3].x = -1.0F * flipX;
verts[3].y = 1.0F * flipY;
verts[0].tex[0] = s0;
verts[0].tex[1] = t0;
verts[0].tex[2] = readAtt->Zoffset;
verts[1].tex[0] = s1;
verts[1].tex[1] = t0;
verts[1].tex[2] = readAtt->Zoffset;
verts[2].tex[0] = s1;
verts[2].tex[1] = t1;
verts[2].tex[2] = readAtt->Zoffset;
verts[3].tex[0] = s0;
verts[3].tex[1] = t1;
verts[3].tex[2] = readAtt->Zoffset;
_mesa_buffer_sub_data(ctx, blit->buf_obj, 0, sizeof(verts), verts);
}
/* setup viewport */
_mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH);
_mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth);
_mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth);
_mesa_DepthMask(do_depth);
_mesa_DepthFunc(GL_ALWAYS);
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
_mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit);
return true;
}
void
_mesa_meta_fb_tex_blit_begin(struct gl_context *ctx,
struct fb_tex_blit_state *blit)
{
/* None of the existing callers preinitialize fb_tex_blit_state to zeros,
* and both use stack variables. If samp_obj_save is not NULL,
* _mesa_reference_sampler_object will try to dereference it. Leaving
* random garbage in samp_obj_save can only lead to crashes.
*
* Since the state isn't persistent across calls, we won't catch ref
* counting problems.
*/
blit->samp_obj_save = NULL;
_mesa_reference_sampler_object(ctx, &blit->samp_obj_save,
ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler);
blit->temp_tex_obj = NULL;
}
void
_mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target,
struct fb_tex_blit_state *blit)
{
struct gl_texture_object *const texObj =
_mesa_get_current_tex_object(ctx, target);
/* Either there is no temporary texture or the temporary texture is bound. */
assert(blit->temp_tex_obj == NULL || blit->temp_tex_obj == texObj);
/* Restore texture object state, the texture binding will be restored by
* _mesa_meta_end(). If the texture is the temporary texture that is about
* to be destroyed, don't bother restoring its state.
*/
if (blit->temp_tex_obj == NULL) {
/* If the target restricts values for base level or max level, we assume
* that the original values were valid.
*/
if (blit->baseLevelSave != texObj->Attrib.BaseLevel)
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
&blit->baseLevelSave, false);
if (blit->maxLevelSave != texObj->Attrib.MaxLevel)
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
&blit->maxLevelSave, false);
/* If ARB_stencil_texturing is not supported, the mode won't have changed. */
if (texObj->StencilSampling != blit->stencilSamplingSave) {
/* GLint so the compiler won't complain about type signedness mismatch
* in the call to _mesa_texture_parameteriv below.
*/
const GLint param = blit->stencilSamplingSave ?
GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
_mesa_texture_parameteriv(ctx, texObj, GL_DEPTH_STENCIL_TEXTURE_MODE,
&param, false);
}
}
_mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, blit->samp_obj_save);
_mesa_reference_sampler_object(ctx, &blit->samp_obj_save, NULL);
_mesa_reference_sampler_object(ctx, &blit->samp_obj, NULL);
_mesa_delete_nameless_texture(ctx, blit->temp_tex_obj);
}
static struct gl_texture_object *
texture_object_from_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer *rb)
{
struct gl_texture_image *texImage;
struct gl_texture_object *texObj;
const GLenum target = GL_TEXTURE_2D;
texObj = ctx->Driver.NewTextureObject(ctx, 0xDEADBEEF, target);
texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) {
_mesa_delete_nameless_texture(ctx, texObj);
return NULL;
}
if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
rb->NeedsFinishRenderTexture = true;
ctx->Driver.FinishRenderTexture(ctx, rb);
}
return texObj;
}
static struct gl_sampler_object *
setup_sampler(struct gl_context *ctx, struct gl_texture_object *texObj,
GLenum target, GLenum filter, GLuint srcLevel)
{
struct gl_sampler_object *samp_obj =
ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF);
if (samp_obj == NULL)
return NULL;
_mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj);
_mesa_set_sampler_filters(ctx, samp_obj, filter, filter);
_mesa_set_sampler_wrap(ctx, samp_obj, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE,
samp_obj->Attrib.WrapR);
/* Prepare src texture state */
_mesa_bind_texture(ctx, target, texObj);
if (target != GL_TEXTURE_RECTANGLE_ARB) {
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
(GLint *) &srcLevel, false);
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
(GLint *) &srcLevel, false);
}
return samp_obj;
}
/**
* Meta implementation of ctx->Driver.BlitFramebuffer() in terms
* of texture mapping and polygon rendering.
*/
GLbitfield
_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
const struct gl_framebuffer *readFb,
const struct gl_framebuffer *drawFb,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
const GLint dstW = abs(dstX1 - dstX0);
const GLint dstH = abs(dstY1 - dstY0);
const GLint dstFlipX = (dstX1 - dstX0) / dstW;
const GLint dstFlipY = (dstY1 - dstY0) / dstH;
struct {
GLint srcX0, srcY0, srcX1, srcY1;
GLint dstX0, dstY0, dstX1, dstY1;
} clip = {
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1
};
const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
ctx->Extensions.ARB_fragment_shader;
/* Multisample blit is not supported. */
if (readFb->Visual.samples > 0)
return mask;
/* Clip a copy of the blit coordinates. If these differ from the input
* coordinates, then we'll set the scissor.
*/
if (!_mesa_clip_blit(ctx, readFb, drawFb,
&clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
&clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
/* clipped/scissored everything away */
return 0;
}
/* Only scissor and FRAMEBUFFER_SRGB affect blit. Leave sRGB alone, but
* save restore scissor as we'll set a custom scissor if necessary.
*/
_mesa_meta_begin(ctx, MESA_META_ALL &
~(MESA_META_DRAW_BUFFERS |
MESA_META_FRAMEBUFFER_SRGB));
/* Dithering shouldn't be performed for glBlitFramebuffer */
_mesa_set_enable(ctx, GL_DITHER, GL_FALSE);
/* If the clipping earlier changed the destination rect at all, then
* enable the scissor to clip to it.
*/
if (clip.dstX0 != dstX0 || clip.dstY0 != dstY0 ||
clip.dstX1 != dstX1 || clip.dstY1 != dstY1) {
_mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE);
_mesa_Scissor(MIN2(clip.dstX0, clip.dstX1),
MIN2(clip.dstY0, clip.dstY1),
abs(clip.dstX0 - clip.dstX1),
abs(clip.dstY0 - clip.dstY1));
}
/* Try faster, direct texture approach first */
if (mask & GL_COLOR_BUFFER_BIT) {
if (blitframebuffer_texture(ctx, readFb, drawFb,
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
filter, dstFlipX, dstFlipY,
use_glsl_version, false)) {
mask &= ~GL_COLOR_BUFFER_BIT;
}
}
if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) {
if (blitframebuffer_texture(ctx, readFb, drawFb,
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
filter, dstFlipX, dstFlipY,
use_glsl_version, true)) {
mask &= ~GL_DEPTH_BUFFER_BIT;
}
}
if (mask & GL_STENCIL_BUFFER_BIT) {
/* XXX can't easily do stencil */
}
_mesa_meta_end(ctx);
return mask;
}
void
_mesa_meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit)
{
if (blit->VAO) {
_mesa_DeleteVertexArrays(1, &blit->VAO);
blit->VAO = 0;
_mesa_reference_buffer_object(ctx, &blit->buf_obj, NULL);
}
_mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_with_depth);
_mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_without_depth);
if (blit->depthTex.tex_obj != NULL) {
_mesa_delete_nameless_texture(ctx, blit->depthTex.tex_obj);
blit->depthTex.tex_obj = NULL;
}
}
void
_mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx,
struct gl_framebuffer *readFb,
struct gl_framebuffer *drawFb,
GLint srcX0, GLint srcY0,
GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
mask = _mesa_meta_BlitFramebuffer(ctx, readFb, drawFb,
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
mask, filter);
if (mask == 0x0)
return;
_swrast_BlitFramebuffer(ctx, readFb, drawFb,
srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
mask, filter);
}

View File

@ -1,379 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Meta operations. Some GL operations can be expressed in terms of
* other GL operations. For example, glBlitFramebuffer() can be done
* with texture mapping and glClear() can be done with polygon rendering.
*
* \author Brian Paul
*/
#include "main/arrayobj.h"
#include "main/blend.h"
#include "main/buffers.h"
#include "main/enums.h"
#include "main/enable.h"
#include "main/fbobject.h"
#include "main/framebuffer.h"
#include "main/macros.h"
#include "main/mipmap.h"
#include "main/teximage.h"
#include "main/texobj.h"
#include "main/texparam.h"
#include "main/varray.h"
#include "main/viewport.h"
#include "drivers/common/meta.h"
#include "program/prog_instruction.h"
/**
* Check if the call to _mesa_meta_GenerateMipmap() will require a
* software fallback. The fallback path will require that the texture
* images are mapped.
* \return GL_TRUE if a fallback is needed, GL_FALSE otherwise
*/
static bool
fallback_required(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj)
{
struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
struct gl_texture_image *baseImage;
GLuint srcLevel;
GLenum status;
/* check for fallbacks */
if (target == GL_TEXTURE_3D) {
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
"glGenerateMipmap() to %s target\n",
_mesa_enum_to_string(target));
return true;
}
srcLevel = texObj->Attrib.BaseLevel;
baseImage = _mesa_select_tex_image(texObj, target, srcLevel);
if (!baseImage) {
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
"glGenerateMipmap() couldn't find base teximage\n");
return true;
}
if (_mesa_is_format_compressed(baseImage->TexFormat)) {
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
"glGenerateMipmap() with %s format\n",
_mesa_get_format_name(baseImage->TexFormat));
return true;
}
if (_mesa_is_format_srgb(baseImage->TexFormat) &&
!ctx->Extensions.EXT_texture_sRGB_decode) {
/* The texture format is sRGB but we can't turn off sRGB->linear
* texture sample conversion. So we won't be able to generate the
* right colors when rendering. Need to use a fallback.
*/
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
"glGenerateMipmap() of sRGB texture without "
"sRGB decode\n");
return true;
}
/*
* Test that we can actually render in the texture's format.
*/
if (mipmap->fb == NULL) {
mipmap->fb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
if (mipmap->fb == NULL) {
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
"glGenerateMipmap() ran out of memory\n");
return true;
}
}
_mesa_meta_framebuffer_texture_image(ctx, mipmap->fb,
GL_COLOR_ATTACHMENT0, baseImage, 0);
status = _mesa_check_framebuffer_status(ctx, mipmap->fb);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
"glGenerateMipmap() got incomplete FBO\n");
return true;
}
return false;
}
void
_mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
struct gen_mipmap_state *mipmap)
{
if (mipmap->VAO == 0)
return;
_mesa_DeleteVertexArrays(1, &mipmap->VAO);
mipmap->VAO = 0;
_mesa_reference_buffer_object(ctx, &mipmap->buf_obj, NULL);
_mesa_reference_sampler_object(ctx, &mipmap->samp_obj, NULL);
_mesa_reference_framebuffer(&mipmap->fb, NULL);
_mesa_meta_blit_shader_table_cleanup(ctx, &mipmap->shaders);
}
/**
* Called via ctx->Driver.GenerateMipmap()
* Note: We don't yet support 3D textures, or texture borders.
*/
void
_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj)
{
struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
struct vertex verts[4];
const GLuint baseLevel = texObj->Attrib.BaseLevel;
const GLuint maxLevel = texObj->Attrib.MaxLevel;
const GLint maxLevelSave = texObj->Attrib.MaxLevel;
const GLboolean genMipmapSave = texObj->Attrib.GenerateMipmap;
const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
ctx->Extensions.ARB_fragment_shader;
GLenum faceTarget;
GLuint dstLevel;
struct gl_sampler_object *samp_obj_save = NULL;
GLint swizzle[4];
GLboolean swizzleSaved = GL_FALSE;
/* GLint so the compiler won't complain about type signedness mismatch in
* the calls to _mesa_texture_parameteriv below.
*/
static const GLint always_false = GL_FALSE;
static const GLint always_true = GL_TRUE;
if (fallback_required(ctx, target, texObj)) {
_mesa_generate_mipmap(ctx, target, texObj);
return;
}
if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
faceTarget = target;
target = GL_TEXTURE_CUBE_MAP;
} else {
faceTarget = target;
}
_mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);
_mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
_mesa_Disable(GL_DITHER);
/* Choose between glsl version and fixed function version of
* GenerateMipmap function.
*/
if (use_glsl_version) {
_mesa_meta_setup_vertex_objects(ctx, &mipmap->VAO, &mipmap->buf_obj, true,
2, 4, 0);
_mesa_meta_setup_blit_shader(ctx, target, false, &mipmap->shaders);
} else {
_mesa_meta_setup_ff_tnl_for_blit(ctx, &mipmap->VAO, &mipmap->buf_obj, 3);
_mesa_set_enable(ctx, target, GL_TRUE);
}
_mesa_reference_sampler_object(ctx, &samp_obj_save,
ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler);
/* We may have been called from glGenerateTextureMipmap with CurrentUnit
* still set to 0, so we don't know when we can skip binding the texture.
* Assume that _mesa_bind_texture will be fast if we're rebinding the same
* texture.
*/
_mesa_bind_texture(ctx, target, texObj);
if (mipmap->samp_obj == NULL) {
mipmap->samp_obj = ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF);
if (mipmap->samp_obj == NULL) {
/* This is a bit lazy. Flag out of memory, and then don't bother to
* clean up. Once out of memory is flagged, the only realistic next
* move is to destroy the context. That will trigger all the right
* clean up.
*/
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenerateMipmap");
return;
}
_mesa_set_sampler_filters(ctx, mipmap->samp_obj, GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR);
_mesa_set_sampler_wrap(ctx, mipmap->samp_obj, GL_CLAMP_TO_EDGE,
GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
}
if (ctx->Extensions.EXT_texture_sRGB_decode) {
const struct gl_texture_image *baseImage =
_mesa_select_tex_image(texObj, target, texObj->Attrib.BaseLevel);
const bool srgb = _mesa_is_format_srgb(baseImage->TexFormat);
_mesa_set_sampler_srgb_decode(ctx, mipmap->samp_obj,
srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT);
_mesa_set_framebuffer_srgb(ctx, srgb);
}
_mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, mipmap->samp_obj);
assert(mipmap->fb != NULL);
_mesa_bind_framebuffers(ctx, mipmap->fb, mipmap->fb);
_mesa_texture_parameteriv(ctx, texObj, GL_GENERATE_MIPMAP, &always_false, false);
if (texObj->Attrib._Swizzle != SWIZZLE_NOOP) {
static const GLint swizzleNoop[4] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
memcpy(swizzle, texObj->Attrib.Swizzle, sizeof(swizzle));
swizzleSaved = GL_TRUE;
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_SWIZZLE_RGBA,
swizzleNoop, false);
}
/* Silence valgrind warnings about reading uninitialized stack. */
memset(verts, 0, sizeof(verts));
/* setup vertex positions */
verts[0].x = -1.0F;
verts[0].y = -1.0F;
verts[1].x = 1.0F;
verts[1].y = -1.0F;
verts[2].x = 1.0F;
verts[2].y = 1.0F;
verts[3].x = -1.0F;
verts[3].y = 1.0F;
/* texture is already locked, unlock now */
_mesa_unlock_texture(ctx, texObj);
_mesa_prepare_mipmap_levels(ctx, texObj, baseLevel, maxLevel);
for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
const struct gl_texture_image *srcImage;
struct gl_texture_image *dstImage;
const GLuint srcLevel = dstLevel - 1;
GLuint layer;
GLsizei srcWidth, srcHeight, srcDepth;
GLsizei dstWidth, dstHeight, dstDepth;
srcImage = _mesa_select_tex_image(texObj, faceTarget, srcLevel);
assert(srcImage->Border == 0);
/* src size */
srcWidth = srcImage->Width;
if (target == GL_TEXTURE_1D_ARRAY) {
srcHeight = 1;
srcDepth = srcImage->Height;
} else {
srcHeight = srcImage->Height;
srcDepth = srcImage->Depth;
}
/* new dst size */
dstWidth = minify(srcWidth, 1);
dstHeight = minify(srcHeight, 1);
dstDepth = target == GL_TEXTURE_3D ? minify(srcDepth, 1) : srcDepth;
if (dstWidth == srcWidth &&
dstHeight == srcHeight &&
dstDepth == srcDepth) {
/* all done */
break;
}
/* Allocate storage for the destination mipmap image(s) */
/* Set MaxLevel large enough to hold the new level when we allocate it */
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
(GLint *) &dstLevel, false);
dstImage = _mesa_select_tex_image(texObj, faceTarget, dstLevel);
/* All done. We either ran out of memory or we would go beyond the last
* valid level of an immutable texture if we continued.
*/
if (dstImage == NULL)
break;
/* limit minification to src level */
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
(GLint *) &srcLevel, false);
/* setup viewport */
_mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight);
_mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);
for (layer = 0; layer < dstDepth; ++layer) {
/* Setup texture coordinates */
_mesa_meta_setup_texture_coords(faceTarget,
layer,
0, 0, /* xoffset, yoffset */
srcWidth, srcHeight, /* img size */
srcWidth, srcHeight, srcDepth,
verts[0].tex,
verts[1].tex,
verts[2].tex,
verts[3].tex);
/* upload vertex data */
_mesa_buffer_data(ctx, mipmap->buf_obj, GL_NONE, sizeof(verts), verts,
GL_DYNAMIC_DRAW, __func__);
_mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
GL_COLOR_ATTACHMENT0, dstImage,
layer);
/* sanity check */
if (_mesa_check_framebuffer_status(ctx, ctx->DrawBuffer) !=
GL_FRAMEBUFFER_COMPLETE) {
_mesa_problem(ctx, "Unexpected incomplete framebuffer in "
"_mesa_meta_GenerateMipmap()");
break;
}
assert(dstWidth == ctx->DrawBuffer->Width);
if (target == GL_TEXTURE_1D_ARRAY) {
assert(dstHeight == 1);
} else {
assert(dstHeight == ctx->DrawBuffer->Height);
}
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
}
_mesa_lock_texture(ctx, texObj); /* relock */
_mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj_save);
_mesa_reference_sampler_object(ctx, &samp_obj_save, NULL);
_mesa_meta_end(ctx);
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, &maxLevelSave,
false);
if (genMipmapSave)
_mesa_texture_parameteriv(ctx, texObj, GL_GENERATE_MIPMAP, &always_true,
false);
if (swizzleSaved)
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_SWIZZLE_RGBA, swizzle,
false);
}

View File

@ -1,257 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
/* KW: a clever asm implementation would nestle integer versions
* of the outcode calculation underneath the division. Gcc won't
* do this, strangely enough, so I only do the divide in
* the case where the cliptest passes. This isn't essential,
* and an asm implementation needn't replicate that behaviour.
*
* \param clip_vec vector of incoming clip-space coords
* \param proj_vec vector of resultant NDC-space projected coords
* \param clipMask resulting array of clip flags
* \param orMask bitwise-OR of clipMask values
* \param andMask bitwise-AND of clipMask values
* \return proj_vec pointer
*/
static GLvector4f * TAG(cliptest_points4)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask,
GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLfloat *from = (GLfloat *)clip_vec->start;
const GLuint count = clip_vec->count;
GLuint c = 0;
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
GLubyte tmpAndMask = *andMask;
GLubyte tmpOrMask = *orMask;
GLuint i;
STRIDE_LOOP {
const GLfloat cx = from[0];
const GLfloat cy = from[1];
const GLfloat cz = from[2];
const GLfloat cw = from[3];
#if defined(__powerpc__)
/* on powerpc cliptest is 17% faster in this way. */
GLuint mask;
mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
mask |= (((cw < cy) << CLIP_TOP_SHIFT));
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
if (viewport_z_clip) {
mask |= (((cw < cz) << CLIP_FAR_SHIFT));
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
}
#else
GLubyte mask = 0;
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
if (viewport_z_clip) {
if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
}
#endif
clipMask[i] = mask;
if (mask) {
c++;
tmpAndMask &= mask;
tmpOrMask |= mask;
vProj[i][0] = 0;
vProj[i][1] = 0;
vProj[i][2] = 0;
vProj[i][3] = 1;
} else {
GLfloat oow = 1.0F / cw;
vProj[i][0] = cx * oow;
vProj[i][1] = cy * oow;
vProj[i][2] = cz * oow;
vProj[i][3] = oow;
}
}
*orMask = tmpOrMask;
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
proj_vec->flags |= VEC_SIZE_4;
proj_vec->size = 4;
proj_vec->count = clip_vec->count;
return proj_vec;
}
/*
* \param clip_vec vector of incoming clip-space coords
* \param proj_vec vector of resultant NDC-space projected coords
* \param clipMask resulting array of clip flags
* \param orMask bitwise-OR of clipMask values
* \param andMask bitwise-AND of clipMask values
* \return clip_vec pointer
*/
static GLvector4f * TAG(cliptest_np_points4)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask,
GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
const GLfloat *from = (GLfloat *)clip_vec->start;
GLuint c = 0;
GLubyte tmpAndMask = *andMask;
GLubyte tmpOrMask = *orMask;
GLuint i;
(void) proj_vec;
STRIDE_LOOP {
const GLfloat cx = from[0];
const GLfloat cy = from[1];
const GLfloat cz = from[2];
const GLfloat cw = from[3];
#if defined(__powerpc__)
/* on powerpc cliptest is 17% faster in this way. */
GLuint mask;
mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
mask |= (((cw < cy) << CLIP_TOP_SHIFT));
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
if (viewport_z_clip) {
mask |= (((cw < cz) << CLIP_FAR_SHIFT));
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
}
#else
GLubyte mask = 0;
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
if (viewport_z_clip) {
if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
}
#endif
clipMask[i] = mask;
if (mask) {
c++;
tmpAndMask &= mask;
tmpOrMask |= mask;
}
}
*orMask = tmpOrMask;
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
return clip_vec;
}
static GLvector4f * TAG(cliptest_points3)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask,
GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
const GLfloat *from = (GLfloat *)clip_vec->start;
GLubyte tmpOrMask = *orMask;
GLubyte tmpAndMask = *andMask;
GLuint i;
(void) proj_vec;
STRIDE_LOOP {
const GLfloat cx = from[0], cy = from[1], cz = from[2];
GLubyte mask = 0;
if (cx > 1.0F) mask |= CLIP_RIGHT_BIT;
else if (cx < -1.0F) mask |= CLIP_LEFT_BIT;
if (cy > 1.0F) mask |= CLIP_TOP_BIT;
else if (cy < -1.0F) mask |= CLIP_BOTTOM_BIT;
if (viewport_z_clip) {
if (cz > 1.0F) mask |= CLIP_FAR_BIT;
else if (cz < -1.0F) mask |= CLIP_NEAR_BIT;
}
clipMask[i] = mask;
tmpOrMask |= mask;
tmpAndMask &= mask;
}
*orMask = tmpOrMask;
*andMask = tmpAndMask;
return clip_vec;
}
static GLvector4f * TAG(cliptest_points2)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask,
GLboolean viewport_z_clip )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
const GLfloat *from = (GLfloat *)clip_vec->start;
GLubyte tmpOrMask = *orMask;
GLubyte tmpAndMask = *andMask;
GLuint i;
(void) proj_vec;
STRIDE_LOOP {
const GLfloat cx = from[0], cy = from[1];
GLubyte mask = 0;
if (cx > 1.0F) mask |= CLIP_RIGHT_BIT;
else if (cx < -1.0F) mask |= CLIP_LEFT_BIT;
if (cy > 1.0F) mask |= CLIP_TOP_BIT;
else if (cy < -1.0F) mask |= CLIP_BOTTOM_BIT;
clipMask[i] = mask;
tmpOrMask |= mask;
tmpAndMask &= mask;
}
*orMask = tmpOrMask;
*andMask = tmpAndMask;
return clip_vec;
}
void TAG(init_c_cliptest)( void )
{
_mesa_clip_tab[4] = TAG(cliptest_points4);
_mesa_clip_tab[3] = TAG(cliptest_points3);
_mesa_clip_tab[2] = TAG(cliptest_points2);
_mesa_clip_np_tab[4] = TAG(cliptest_np_points4);
_mesa_clip_np_tab[3] = TAG(cliptest_points3);
_mesa_clip_np_tab[2] = TAG(cliptest_points2);
}

View File

@ -1,86 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
#define COPY_FUNC( BITS ) \
static void TAG2(copy, BITS)( GLvector4f *to, const GLvector4f *f ) \
{ \
GLfloat (*t)[4] = (GLfloat (*)[4])to->start; \
GLfloat *from = f->start; \
GLuint stride = f->stride; \
GLuint count = to->count; \
GLuint i; \
\
if (BITS) \
STRIDE_LOOP { \
if (BITS&1) t[i][0] = from[0]; \
if (BITS&2) t[i][1] = from[1]; \
if (BITS&4) t[i][2] = from[2]; \
if (BITS&8) t[i][3] = from[3]; \
} \
}
/* We got them all here:
*/
COPY_FUNC( 0x0 ) /* noop */
COPY_FUNC( 0x1 )
COPY_FUNC( 0x2 )
COPY_FUNC( 0x3 )
COPY_FUNC( 0x4 )
COPY_FUNC( 0x5 )
COPY_FUNC( 0x6 )
COPY_FUNC( 0x7 )
COPY_FUNC( 0x8 )
COPY_FUNC( 0x9 )
COPY_FUNC( 0xa )
COPY_FUNC( 0xb )
COPY_FUNC( 0xc )
COPY_FUNC( 0xd )
COPY_FUNC( 0xe )
COPY_FUNC( 0xf )
static void TAG2(init_copy, 0)( void )
{
_mesa_copy_tab[0x0] = TAG2(copy, 0x0);
_mesa_copy_tab[0x1] = TAG2(copy, 0x1);
_mesa_copy_tab[0x2] = TAG2(copy, 0x2);
_mesa_copy_tab[0x3] = TAG2(copy, 0x3);
_mesa_copy_tab[0x4] = TAG2(copy, 0x4);
_mesa_copy_tab[0x5] = TAG2(copy, 0x5);
_mesa_copy_tab[0x6] = TAG2(copy, 0x6);
_mesa_copy_tab[0x7] = TAG2(copy, 0x7);
_mesa_copy_tab[0x8] = TAG2(copy, 0x8);
_mesa_copy_tab[0x9] = TAG2(copy, 0x9);
_mesa_copy_tab[0xa] = TAG2(copy, 0xa);
_mesa_copy_tab[0xb] = TAG2(copy, 0xb);
_mesa_copy_tab[0xc] = TAG2(copy, 0xc);
_mesa_copy_tab[0xd] = TAG2(copy, 0xd);
_mesa_copy_tab[0xe] = TAG2(copy, 0xe);
_mesa_copy_tab[0xf] = TAG2(copy, 0xf);
}

View File

@ -1,102 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
/* Note - respects the stride of the output vector.
*/
static void TAG(dotprod_vec2)( GLfloat *out,
GLuint outstride,
const GLvector4f *coord_vec,
const GLfloat plane[4] )
{
GLuint stride = coord_vec->stride;
GLfloat *coord = coord_vec->start;
GLuint count = coord_vec->count;
GLuint i;
const GLfloat plane0 = plane[0], plane1 = plane[1], plane3 = plane[3];
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
*out = (coord[0] * plane0 +
coord[1] * plane1 +
plane3);
}
}
static void TAG(dotprod_vec3)( GLfloat *out,
GLuint outstride,
const GLvector4f *coord_vec,
const GLfloat plane[4] )
{
GLuint stride = coord_vec->stride;
GLfloat *coord = coord_vec->start;
GLuint count = coord_vec->count;
GLuint i;
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2];
const GLfloat plane3 = plane[3];
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
*out = (coord[0] * plane0 +
coord[1] * plane1 +
coord[2] * plane2 +
plane3);
}
}
static void TAG(dotprod_vec4)( GLfloat *out,
GLuint outstride,
const GLvector4f *coord_vec,
const GLfloat plane[4] )
{
GLuint stride = coord_vec->stride;
GLfloat *coord = coord_vec->start;
GLuint count = coord_vec->count;
GLuint i;
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2];
const GLfloat plane3 = plane[3];
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
*out = (coord[0] * plane0 +
coord[1] * plane1 +
coord[2] * plane2 +
coord[3] * plane3);
}
}
static void TAG(init_dotprod)( void )
{
_mesa_dotprod_tab[2] = TAG(dotprod_vec2);
_mesa_dotprod_tab[3] = TAG(dotprod_vec3);
_mesa_dotprod_tab[4] = TAG(dotprod_vec4);
}

View File

@ -1,390 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
/* Functions to tranform a vector of normals. This includes applying
* the transformation matrix, rescaling and normalization.
*/
/*
* mat - the 4x4 transformation matrix
* scale - uniform scale factor of the transformation matrix (not always used)
* in - the source vector of normals
* lengths - length of each incoming normal (may be NULL) (a display list
* optimization)
* dest - the destination vector of normals
*/
static void
TAG(transform_normalize_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
GLuint i;
if (!lengths) {
STRIDE_LOOP {
GLfloat tx, ty, tz;
{
const GLfloat ux = from[0], uy = from[1], uz = from[2];
tx = ux * m0 + uy * m1 + uz * m2;
ty = ux * m4 + uy * m5 + uz * m6;
tz = ux * m8 + uy * m9 + uz * m10;
}
{
GLdouble len = tx*tx + ty*ty + tz*tz;
if (len > 1e-20) {
GLfloat scale = 1.0f / sqrtf(len);
out[i][0] = tx * scale;
out[i][1] = ty * scale;
out[i][2] = tz * scale;
}
else {
out[i][0] = out[i][1] = out[i][2] = 0;
}
}
}
}
else {
if (scale != 1.0f) {
m0 *= scale, m4 *= scale, m8 *= scale;
m1 *= scale, m5 *= scale, m9 *= scale;
m2 *= scale, m6 *= scale, m10 *= scale;
}
STRIDE_LOOP {
GLfloat tx, ty, tz;
{
const GLfloat ux = from[0], uy = from[1], uz = from[2];
tx = ux * m0 + uy * m1 + uz * m2;
ty = ux * m4 + uy * m5 + uz * m6;
tz = ux * m8 + uy * m9 + uz * m10;
}
{
GLfloat len = lengths[i];
out[i][0] = tx * len;
out[i][1] = ty * len;
out[i][2] = tz * len;
}
}
}
dest->count = in->count;
}
static void
TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
GLfloat m0 = m[0];
GLfloat m5 = m[5];
GLfloat m10 = m[10];
GLuint i;
if (!lengths) {
STRIDE_LOOP {
GLfloat tx, ty, tz;
{
const GLfloat ux = from[0], uy = from[1], uz = from[2];
tx = ux * m0 ;
ty = uy * m5 ;
tz = uz * m10;
}
{
GLdouble len = tx*tx + ty*ty + tz*tz;
if (len > 1e-20) {
GLfloat scale = 1.0f / sqrtf(len);
out[i][0] = tx * scale;
out[i][1] = ty * scale;
out[i][2] = tz * scale;
}
else {
out[i][0] = out[i][1] = out[i][2] = 0;
}
}
}
}
else {
m0 *= scale;
m5 *= scale;
m10 *= scale;
STRIDE_LOOP {
GLfloat tx, ty, tz;
{
const GLfloat ux = from[0], uy = from[1], uz = from[2];
tx = ux * m0 ;
ty = uy * m5 ;
tz = uz * m10;
}
{
GLfloat len = lengths[i];
out[i][0] = tx * len;
out[i][1] = ty * len;
out[i][2] = tz * len;
}
}
}
dest->count = in->count;
}
static void
TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
const GLfloat m0 = scale*m[0];
const GLfloat m5 = scale*m[5];
const GLfloat m10 = scale*m[10];
GLuint i;
(void) lengths;
STRIDE_LOOP {
GLfloat ux = from[0], uy = from[1], uz = from[2];
out[i][0] = ux * m0;
out[i][1] = uy * m5;
out[i][2] = uz * m10;
}
dest->count = in->count;
}
static void
TAG(transform_rescale_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
/* Since we are unlikely to have < 3 vertices in the buffer,
* it makes sense to pre-multiply by scale.
*/
const GLfloat *m = mat->inv;
const GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8];
const GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9];
const GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10];
GLuint i;
(void) lengths;
STRIDE_LOOP {
GLfloat ux = from[0], uy = from[1], uz = from[2];
out[i][0] = ux * m0 + uy * m1 + uz * m2;
out[i][1] = ux * m4 + uy * m5 + uz * m6;
out[i][2] = ux * m8 + uy * m9 + uz * m10;
}
dest->count = in->count;
}
static void
TAG(transform_normals_no_rot)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
const GLfloat m0 = m[0];
const GLfloat m5 = m[5];
const GLfloat m10 = m[10];
GLuint i;
(void) scale;
(void) lengths;
STRIDE_LOOP {
GLfloat ux = from[0], uy = from[1], uz = from[2];
out[i][0] = ux * m0;
out[i][1] = uy * m5;
out[i][2] = uz * m10;
}
dest->count = in->count;
}
static void
TAG(transform_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
GLuint i;
(void) scale;
(void) lengths;
STRIDE_LOOP {
GLfloat ux = from[0], uy = from[1], uz = from[2];
out[i][0] = ux * m0 + uy * m1 + uz * m2;
out[i][1] = ux * m4 + uy * m5 + uz * m6;
out[i][2] = ux * m8 + uy * m9 + uz * m10;
}
dest->count = in->count;
}
static void
TAG(normalize_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
GLuint i;
(void) mat;
(void) scale;
if (lengths) {
STRIDE_LOOP {
const GLfloat x = from[0], y = from[1], z = from[2];
GLfloat invlen = lengths[i];
out[i][0] = x * invlen;
out[i][1] = y * invlen;
out[i][2] = z * invlen;
}
}
else {
STRIDE_LOOP {
const GLfloat x = from[0], y = from[1], z = from[2];
GLdouble len = x * x + y * y + z * z;
if (len > 1e-50) {
len = 1.0f / sqrtf(len);
out[i][0] = (GLfloat)(x * len);
out[i][1] = (GLfloat)(y * len);
out[i][2] = (GLfloat)(z * len);
}
else {
out[i][0] = x;
out[i][1] = y;
out[i][2] = z;
}
}
}
dest->count = in->count;
}
static void
TAG(rescale_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
GLuint i;
(void) mat;
(void) lengths;
STRIDE_LOOP {
SCALE_SCALAR_3V( out[i], scale, from );
}
dest->count = in->count;
}
static void
TAG(init_c_norm_transform)( void )
{
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
TAG(transform_normals_no_rot);
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
TAG(transform_rescale_normals_no_rot);
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
TAG(transform_normalize_normals_no_rot);
_mesa_normal_tab[NORM_TRANSFORM] =
TAG(transform_normals);
_mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
TAG(transform_rescale_normals);
_mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
TAG(transform_normalize_normals);
_mesa_normal_tab[NORM_RESCALE] =
TAG(rescale_normals);
_mesa_normal_tab[NORM_NORMALIZE] =
TAG(normalize_normals);
}

View File

@ -1,123 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Matrix/vertex/vector transformation stuff
*
*
* NOTES:
* 1. 4x4 transformation matrices are stored in memory in column major order.
* 2. Points/vertices are to be thought of as column vectors.
* 3. Transformation of a point p by a matrix M is: p' = M * p
*/
#include "c99_math.h"
#include "main/glheader.h"
#include "main/macros.h"
#include "m_eval.h"
#include "m_matrix.h"
#include "m_translate.h"
#include "m_xform.h"
#ifdef DEBUG_MATH
#include "m_debug.h"
#endif
#ifdef USE_X86_ASM
#include "x86/common_x86_asm.h"
#endif
#ifdef USE_X86_64_ASM
#include "x86-64/x86-64.h"
#endif
#ifdef USE_SPARC_ASM
#include "sparc/sparc.h"
#endif
clip_func _mesa_clip_tab[5];
clip_func _mesa_clip_np_tab[5];
dotprod_func _mesa_dotprod_tab[5];
vec_copy_func _mesa_copy_tab[0x10];
normal_func _mesa_normal_tab[0xf];
transform_func *_mesa_transform_tab[5];
/* Raw data format used for:
* - Object-to-eye transform prior to culling, although this too
* could be culled under some circumstances.
* - Eye-to-clip transform (via the function above).
* - Cliptesting
* - And everything else too, if culling happens to be disabled.
*
* GH: It's used for everything now, as clipping/culling is done
* elsewhere (most often by the driver itself).
*/
#define TAG(x) x
#define TAG2(x,y) x##y
#define STRIDE_LOOP for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) )
#define LOOP for ( i = 0 ; i < n ; i++ )
#define ARGS
#include "m_xform_tmp.h"
#include "m_clip_tmp.h"
#include "m_norm_tmp.h"
#include "m_dotprod_tmp.h"
#include "m_copy_tmp.h"
#undef TAG
#undef TAG2
#undef LOOP
#undef ARGS
/*
* This is called only once. It initializes several tables with pointers
* to optimized transformation functions. This is where we can test for
* AMD 3Dnow! capability, Intel SSE, etc. and hook in the right code.
*/
void
_math_init_transformation( void )
{
init_c_transformations();
init_c_norm_transform();
init_c_cliptest();
init_copy0();
init_dotprod();
#ifdef DEBUG_MATH
_math_test_all_transform_functions( "default" );
_math_test_all_normal_transform_functions( "default" );
_math_test_all_cliptest_functions( "default" );
#endif
#ifdef USE_X86_ASM
_mesa_init_all_x86_transform_asm();
#elif defined( USE_SPARC_ASM )
_mesa_init_all_sparc_transform_asm();
#elif defined( USE_X86_64_ASM )
_mesa_init_all_x86_64_transform_asm();
#endif
}

View File

@ -1,810 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
/*----------------------------------------------------------------------
* Begin Keith's new code
*
*----------------------------------------------------------------------
*/
/* KW: Fixed stride, now measured in bytes as is the OpenGL array stride.
*/
/* KW: These are now parameterized to produce two versions, one
* which transforms all incoming points, and a second which
* takes notice of a cullmask array, and only transforms
* unculled vertices.
*/
/* KW: 1-vectors can sneak into the texture pipeline via the array
* interface. These functions are here because I want consistant
* treatment of the vertex sizes and a lazy strategy for
* cleaning unused parts of the vector, and so as not to exclude
* them from the vertex array interface.
*
* Under our current analysis of matrices, there is no way that
* the product of a matrix and a 1-vector can remain a 1-vector,
* with the exception of the identity transform.
*/
/* KW: No longer zero-pad outgoing vectors. Now that external
* vectors can get into the pipeline we cannot ever assume
* that there is more to a vector than indicated by its
* size.
*/
/* KW: Now uses clipmask and a flag to allow us to skip both/either
* cliped and/or culled vertices.
*/
/* GH: Not any more -- it's easier (and faster) to just process the
* entire vector. Clipping and culling are handled further down
* the pipe, most often during or after the conversion to some
* driver-specific vertex format.
*/
static void
TAG(transform_points1_general)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m12 = m[12];
const GLfloat m1 = m[1], m13 = m[13];
const GLfloat m2 = m[2], m14 = m[14];
const GLfloat m3 = m[3], m15 = m[15];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m1 * ox + m13;
to[i][2] = m2 * ox + m14;
to[i][3] = m3 * ox + m15;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points1_identity)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLuint count = from_vec->count;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint i;
(void) m;
if (to_vec == from_vec) return;
STRIDE_LOOP {
to[i][0] = from[0];
}
to_vec->size = 1;
to_vec->flags |= VEC_SIZE_1;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points1_2d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1];
const GLfloat m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m1 * ox + m13;
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points1_2d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m13;
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points1_3d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m1 * ox + m13;
to[i][2] = m2 * ox + m14;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points1_3d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m13;
to[i][2] = m14;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points1_perspective)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox ;
to[i][1] = 0 ;
to[i][2] = m14;
to[i][3] = 0;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
/* 2-vectors, which are a lot more relevant than 1-vectors, are
* present early in the geometry pipeline and throughout the
* texture pipeline.
*/
static void
TAG(transform_points2_general)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m4 = m[4], m12 = m[12];
const GLfloat m1 = m[1], m5 = m[5], m13 = m[13];
const GLfloat m2 = m[2], m6 = m[6], m14 = m[14];
const GLfloat m3 = m[3], m7 = m[7], m15 = m[15];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m4 * oy + m12;
to[i][1] = m1 * ox + m5 * oy + m13;
to[i][2] = m2 * ox + m6 * oy + m14;
to[i][3] = m3 * ox + m7 * oy + m15;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points2_identity)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
GLuint i;
(void) m;
if (to_vec == from_vec) return;
STRIDE_LOOP {
to[i][0] = from[0];
to[i][1] = from[1];
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points2_2d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
const GLfloat m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m4 * oy + m12;
to[i][1] = m1 * ox + m5 * oy + m13;
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points2_2d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m12;
to[i][1] = m5 * oy + m13;
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points2_3d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
const GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m4 * oy + m12;
to[i][1] = m1 * ox + m5 * oy + m13;
to[i][2] = m2 * ox + m6 * oy + m14;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
/* I would actually say this was a fairly important function, from
* a texture transformation point of view.
*/
static void
TAG(transform_points2_3d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m12;
to[i][1] = m5 * oy + m13;
to[i][2] = m14;
}
if (m14 == 0) {
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
} else {
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
}
to_vec->count = from_vec->count;
}
static void
TAG(transform_points2_perspective)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox ;
to[i][1] = m5 * oy ;
to[i][2] = m14;
to[i][3] = 0;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points3_general)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12;
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13;
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points3_identity)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
GLuint i;
(void) m;
if (to_vec == from_vec) return;
STRIDE_LOOP {
to[i][0] = from[0];
to[i][1] = from[1];
to[i][2] = from[2];
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points3_2d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
const GLfloat m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m4 * oy + m12 ;
to[i][1] = m1 * ox + m5 * oy + m13 ;
to[i][2] = + oz ;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points3_2d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m12 ;
to[i][1] = m5 * oy + m13 ;
to[i][2] = + oz ;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points3_3d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 ;
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 ;
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 ;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
/* previously known as ortho...
*/
static void
TAG(transform_points3_3d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5];
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m12 ;
to[i][1] = m5 * oy + m13 ;
to[i][2] = m10 * oz + m14 ;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points3_perspective)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
const GLfloat m10 = m[10], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m8 * oz ;
to[i][1] = m5 * oy + m9 * oz ;
to[i][2] = m10 * oz + m14 ;
to[i][3] = -oz ;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points4_general)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow;
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow;
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points4_identity)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
GLuint i;
(void) m;
if (to_vec == from_vec) return;
STRIDE_LOOP {
to[i][0] = from[0];
to[i][1] = from[1];
to[i][2] = from[2];
to[i][3] = from[3];
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points4_2d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
const GLfloat m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m4 * oy + m12 * ow;
to[i][1] = m1 * ox + m5 * oy + m13 * ow;
to[i][2] = + oz ;
to[i][3] = ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points4_2d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m12 * ow;
to[i][1] = m5 * oy + m13 * ow;
to[i][2] = + oz ;
to[i][3] = ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points4_3d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow;
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow;
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
to[i][3] = ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points4_3d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5];
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m12 * ow;
to[i][1] = m5 * oy + m13 * ow;
to[i][2] = m10 * oz + m14 * ow;
to[i][3] = ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static void
TAG(transform_points4_perspective)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
const GLfloat m10 = m[10], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m8 * oz ;
to[i][1] = m5 * oy + m9 * oz ;
to[i][2] = m10 * oz + m14 * ow ;
to[i][3] = -oz ;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
static transform_func TAG(transform_tab_1)[7];
static transform_func TAG(transform_tab_2)[7];
static transform_func TAG(transform_tab_3)[7];
static transform_func TAG(transform_tab_4)[7];
/* Similar functions could be called several times, with more highly
* optimized routines overwriting the arrays. This only occurs during
* startup.
*/
static void TAG(init_c_transformations)( void )
{
#define TAG_TAB _mesa_transform_tab
#define TAG_TAB_1 TAG(transform_tab_1)
#define TAG_TAB_2 TAG(transform_tab_2)
#define TAG_TAB_3 TAG(transform_tab_3)
#define TAG_TAB_4 TAG(transform_tab_4)
TAG_TAB[1] = TAG_TAB_1;
TAG_TAB[2] = TAG_TAB_2;
TAG_TAB[3] = TAG_TAB_3;
TAG_TAB[4] = TAG_TAB_4;
/* 1-D points (ie texcoords) */
TAG_TAB_1[MATRIX_GENERAL] = TAG(transform_points1_general);
TAG_TAB_1[MATRIX_IDENTITY] = TAG(transform_points1_identity);
TAG_TAB_1[MATRIX_3D_NO_ROT] = TAG(transform_points1_3d_no_rot);
TAG_TAB_1[MATRIX_PERSPECTIVE] = TAG(transform_points1_perspective);
TAG_TAB_1[MATRIX_2D] = TAG(transform_points1_2d);
TAG_TAB_1[MATRIX_2D_NO_ROT] = TAG(transform_points1_2d_no_rot);
TAG_TAB_1[MATRIX_3D] = TAG(transform_points1_3d);
/* 2-D points */
TAG_TAB_2[MATRIX_GENERAL] = TAG(transform_points2_general);
TAG_TAB_2[MATRIX_IDENTITY] = TAG(transform_points2_identity);
TAG_TAB_2[MATRIX_3D_NO_ROT] = TAG(transform_points2_3d_no_rot);
TAG_TAB_2[MATRIX_PERSPECTIVE] = TAG(transform_points2_perspective);
TAG_TAB_2[MATRIX_2D] = TAG(transform_points2_2d);
TAG_TAB_2[MATRIX_2D_NO_ROT] = TAG(transform_points2_2d_no_rot);
TAG_TAB_2[MATRIX_3D] = TAG(transform_points2_3d);
/* 3-D points */
TAG_TAB_3[MATRIX_GENERAL] = TAG(transform_points3_general);
TAG_TAB_3[MATRIX_IDENTITY] = TAG(transform_points3_identity);
TAG_TAB_3[MATRIX_3D_NO_ROT] = TAG(transform_points3_3d_no_rot);
TAG_TAB_3[MATRIX_PERSPECTIVE] = TAG(transform_points3_perspective);
TAG_TAB_3[MATRIX_2D] = TAG(transform_points3_2d);
TAG_TAB_3[MATRIX_2D_NO_ROT] = TAG(transform_points3_2d_no_rot);
TAG_TAB_3[MATRIX_3D] = TAG(transform_points3_3d);
/* 4-D points */
TAG_TAB_4[MATRIX_GENERAL] = TAG(transform_points4_general);
TAG_TAB_4[MATRIX_IDENTITY] = TAG(transform_points4_identity);
TAG_TAB_4[MATRIX_3D_NO_ROT] = TAG(transform_points4_3d_no_rot);
TAG_TAB_4[MATRIX_PERSPECTIVE] = TAG(transform_points4_perspective);
TAG_TAB_4[MATRIX_2D] = TAG(transform_points4_2d);
TAG_TAB_4[MATRIX_2D_NO_ROT] = TAG(transform_points4_2d_no_rot);
TAG_TAB_4[MATRIX_3D] = TAG(transform_points4_3d);
#undef TAG_TAB
#undef TAG_TAB_1
#undef TAG_TAB_2
#undef TAG_TAB_3
#undef TAG_TAB_4
}

View File

@ -351,124 +351,6 @@ files_libmesa_common = files(
'x86/common_x86.c',
)
# mesa files
files_libmesa_classic = files(
'math/m_clip_tmp.h',
'math/m_copy_tmp.h',
'math/m_dotprod_tmp.h',
'math/m_norm_tmp.h',
'math/m_xform.c',
'math/m_xform.h',
'math/m_xform_tmp.h',
'tnl/t_context.c',
'tnl/t_context.h',
'tnl/t_draw.c',
'tnl/tnl.h',
'tnl/t_pipeline.c',
'tnl/t_pipeline.h',
'tnl/t_rebase.c',
'tnl/t_split.c',
'tnl/t_split_copy.c',
'tnl/t_split.h',
'tnl/t_split_inplace.c',
'tnl/t_vb_cliptmp.h',
'tnl/t_vb_fog.c',
'tnl/t_vb_light.c',
'tnl/t_vb_lighttmp.h',
'tnl/t_vb_normals.c',
'tnl/t_vb_points.c',
'tnl/t_vb_program.c',
'tnl/t_vb_render.c',
'tnl/t_vb_rendertmp.h',
'tnl/t_vb_texgen.c',
'tnl/t_vb_texmat.c',
'tnl/t_vb_vertex.c',
'tnl/t_vertex.c',
'tnl/t_vertex_generic.c',
'tnl/t_vertex.h',
'tnl/t_vertex_sse.c',
'tnl/t_vp_build.c',
'tnl/t_vp_build.h',
'swrast/s_aaline.c',
'swrast/s_aaline.h',
'swrast/s_aalinetemp.h',
'swrast/s_aatriangle.c',
'swrast/s_aatriangle.h',
'swrast/s_aatritemp.h',
'swrast/s_alpha.c',
'swrast/s_alpha.h',
'swrast/s_atifragshader.c',
'swrast/s_atifragshader.h',
'swrast/s_bitmap.c',
'swrast/s_blend.c',
'swrast/s_blend.h',
'swrast/s_blit.c',
'swrast/s_chan.h',
'swrast/s_clear.c',
'swrast/s_context.c',
'swrast/s_context.h',
'swrast/s_copypix.c',
'swrast/s_depth.c',
'swrast/s_depth.h',
'swrast/s_drawpix.c',
'swrast_setup/ss_tritmp.h',
'swrast_setup/ss_vb.h',
'swrast_setup/swrast_setup.h',
'swrast/s_feedback.c',
'swrast/s_feedback.h',
'swrast/s_fog.c',
'swrast/s_fog.h',
'swrast/s_fragprog.c',
'swrast/s_fragprog.h',
'swrast/s_lines.c',
'swrast/s_lines.h',
'swrast/s_linetemp.h',
'swrast/s_logic.c',
'swrast/s_logic.h',
'swrast/s_masking.c',
'swrast/s_masking.h',
'swrast/s_points.c',
'swrast/s_points.h',
'swrast/s_renderbuffer.c',
'swrast/s_renderbuffer.h',
'swrast/s_span.c',
'swrast/s_span.h',
'swrast/s_stencil.c',
'swrast/s_stencil.h',
'swrast/s_texcombine.c',
'swrast/s_texcombine.h',
'swrast/s_texfetch.c',
'swrast/s_texfetch.h',
'swrast/s_texfetch_tmp.h',
'swrast/s_texfilter.c',
'swrast/s_texfilter.h',
'swrast/s_texrender.c',
'swrast/s_texture.c',
'swrast/s_triangle.c',
'swrast/s_triangle.h',
'swrast/s_tritemp.h',
'swrast/swrast.h',
'swrast/s_zoom.c',
'swrast/s_zoom.h',
'swrast_setup/ss_context.c',
'swrast_setup/ss_context.h',
'swrast_setup/ss_triangle.c',
'swrast_setup/ss_triangle.h',
'drivers/common/driverfuncs.c',
'drivers/common/driverfuncs.h',
'drivers/common/meta_blit.c',
'drivers/common/meta_generate_mipmap.c',
'drivers/common/meta.c',
'drivers/common/meta.h',
'x86/x86_xform.c',
'x86/3dnow.c',
'x86/sse.c',
'x86/rtasm/x86sse.c',
'x86/rtasm/x86sse.h',
'sparc/sparc.c',
'x86-64/x86-64.c',
)
files_libmesa_gallium = files(
'state_tracker/st_atifs_to_nir.c',
'state_tracker/st_atifs_to_nir.h',
@ -612,44 +494,15 @@ inc_libmesa_asm = []
if with_asm_arch == 'x86'
files_libmesa_common += files(
'x86/assyntax.h',
'x86/clip_args.h',
'x86/norm_args.h',
'x86/xform_args.h',
'x86/common_x86_asm.S',
'x86/common_x86_asm.h',
'x86/common_x86_features.h',
'x86/x86_xform.h',
'x86/x86_xform2.S',
'x86/x86_xform3.S',
'x86/x86_xform4.S',
'x86/x86_cliptest.S',
'x86/mmx.h',
'x86/mmx_blend.S',
'x86/mmx_blendtmp.h',
'x86/3dnow.h',
'x86/3dnow_xform1.S',
'x86/3dnow_xform2.S',
'x86/3dnow_xform3.S',
'x86/3dnow_xform4.S',
'x86/sse.h',
'x86/sse_xform1.S',
'x86/sse_xform2.S',
'x86/sse_xform3.S',
'x86/sse_xform4.S',
'x86/sse_normal.S',
'x86/read_rgba_span_x86.S',
)
inc_libmesa_asm = include_directories('x86')
elif with_asm_arch == 'x86_64'
files_libmesa_common += files('x86-64/x86-64.h', 'x86-64/xform4.S')
inc_libmesa_asm = include_directories('x86-64')
elif with_asm_arch == 'sparc'
files_libmesa_common += files(
'sparc/sparc_clip.S',
'sparc/norm.S',
'sparc/xform.S',
)
inc_libmesa_asm = include_directories('sparc')
endif
format_fallback_c = custom_target(
@ -733,18 +586,6 @@ libmesa_common = static_library(
build_by_default : false,
)
libmesa_classic = static_library(
'mesa_classic',
files_libmesa_classic,
c_args : [c_msvc_compat_args],
cpp_args : [cpp_msvc_compat_args],
gnu_symbol_visibility : 'hidden',
include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_libmesa_asm, include_directories('main')],
link_with : [libmesa_common, libglsl, libmesa_sse41],
dependencies : [idep_nir_headers, idep_mesautil],
build_by_default : false,
)
libmesa_gallium = static_library(
'mesa_gallium',
files_libmesa_gallium,

View File

@ -1,605 +0,0 @@
#include "sparc_matrix.h"
.register %g2, #scratch
.register %g3, #scratch
.text
#ifdef __arch64__
#define STACK_VAR_OFF (2047 + (8 * 16))
#else
#define STACK_VAR_OFF (4 * 16)
#endif
/* Newton-Raphson approximation turns out to be slower
* (and less accurate) than direct fsqrts/fdivs.
*/
#define ONE_DOT_ZERO 0x3f800000
.globl _mesa_sparc_transform_normalize_normals
_mesa_sparc_transform_normalize_normals:
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
sethi %hi(ONE_DOT_ZERO), %g2
sub %sp, 16, %sp
st %g2, [%sp + STACK_VAR_OFF+0x0]
st %o1, [%sp + STACK_VAR_OFF+0x4]
ld [%sp + STACK_VAR_OFF+0x0], %f12 ! f12 = 1.0f
ld [%sp + STACK_VAR_OFF+0x4], %f15 ! f15 = scale
add %sp, 16, %sp
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
LDMATRIX_0_1_2_4_5_6_8_9_10(%o0)
/* dest->count = in->count */
st %g1, [%o4 + V4F_COUNT]
cmp %g1, 1
bl 7f
cmp %o3, 0
bne 4f
clr %o4 ! 'i' for STRIDE_LOOP
1: /* LENGTHS == NULL */
ld [%o5 + 0x00], %f0 ! ux = from[0]
ld [%o5 + 0x04], %f1 ! uy = from[1]
ld [%o5 + 0x08], %f2 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
/* tx (f3) = (ux * m0) + (uy * m1) + (uz * m2)
* ty (f5) = (ux * m4) + (uy * m5) + (uz * m6)
* tz (f7) = (ux * m8) + (uy * m9) + (uz * m10)
*/
fmuls %f0, M0, %f3 ! FGM Group
fmuls %f1, M1, %f4 ! FGM Group
fmuls %f0, M4, %f5 ! FGM Group
fmuls %f1, M5, %f6 ! FGM Group
fmuls %f0, M8, %f7 ! FGM Group f3 available
fmuls %f1, M9, %f8 ! FGM Group f4 available
fadds %f3, %f4, %f3 ! FGA
fmuls %f2, M2, %f10 ! FGM Group f5 available
fmuls %f2, M6, %f0 ! FGM Group f6 available
fadds %f5, %f6, %f5 ! FGA
fmuls %f2, M10, %f4 ! FGM Group f7 available
fadds %f7, %f8, %f7 ! FGA Group f8,f3 available
fadds %f3, %f10, %f3 ! FGA Group f10 available
fadds %f5, %f0, %f5 ! FGA Group stall f0,f5 available
fadds %f7, %f4, %f7 ! FGA Group stall f4,f7 available
/* f3=tx, f5=ty, f7=tz */
/* len (f6) = (tx * tx) + (ty * ty) + (tz * tz) */
fmuls %f3, %f3, %f6 ! FGM Group f3 available
fmuls %f5, %f5, %f8 ! FGM Group f5 available
fmuls %f7, %f7, %f10 ! FGM Group f7 available
fadds %f6, %f8, %f6 ! FGA Group 2cyc stall f6,f8 available
fadds %f6, %f10, %f6 ! FGA Group 4cyc stall f6,f10 available
/* scale (f6) = 1.0 / sqrt(len) */
fsqrts %f6, %f6 ! FDIV 20 cycles
fdivs %f12, %f6, %f6 ! FDIV 14 cycles
fmuls %f3, %f6, %f3
st %f3, [%g3 + 0x00] ! out[i][0] = tx * scale
fmuls %f5, %f6, %f5
st %f5, [%g3 + 0x04] ! out[i][1] = ty * scale
fmuls %f7, %f6, %f7
st %f7, [%g3 + 0x08] ! out[i][2] = tz * scale
cmp %o4, %g1 ! continue if (i < count)
bl 1b
add %g3, 0x10, %g3 ! advance out vector pointer
ba 7f
nop
4: /* LENGTHS != NULL */
fmuls M0, %f15, M0
fmuls M1, %f15, M1
fmuls M2, %f15, M2
fmuls M4, %f15, M4
fmuls M5, %f15, M5
fmuls M6, %f15, M6
fmuls M8, %f15, M8
fmuls M9, %f15, M9
fmuls M10, %f15, M10
5:
ld [%o5 + 0x00], %f0 ! ux = from[0]
ld [%o5 + 0x04], %f1 ! uy = from[1]
ld [%o5 + 0x08], %f2 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
/* tx (f3) = (ux * m0) + (uy * m1) + (uz * m2)
* ty (f5) = (ux * m4) + (uy * m5) + (uz * m6)
* tz (f7) = (ux * m8) + (uy * m9) + (uz * m10)
*/
fmuls %f0, M0, %f3 ! FGM Group
fmuls %f1, M1, %f4 ! FGM Group
fmuls %f0, M4, %f5 ! FGM Group
fmuls %f1, M5, %f6 ! FGM Group
fmuls %f0, M8, %f7 ! FGM Group f3 available
fmuls %f1, M9, %f8 ! FGM Group f4 available
fadds %f3, %f4, %f3 ! FGA
fmuls %f2, M2, %f10 ! FGM Group f5 available
fmuls %f2, M6, %f0 ! FGM Group f6 available
fadds %f5, %f6, %f5 ! FGA
fmuls %f2, M10, %f4 ! FGM Group f7 available
fadds %f7, %f8, %f7 ! FGA Group f8,f3 available
fadds %f3, %f10, %f3 ! FGA Group f10 available
ld [%o3], %f13 ! LSU
fadds %f5, %f0, %f5 ! FGA Group stall f0,f5 available
add %o3, 4, %o3 ! IEU0
fadds %f7, %f4, %f7 ! FGA Group stall f4,f7 available
/* f3=tx, f5=ty, f7=tz, f13=lengths[i] */
fmuls %f3, %f13, %f3
st %f3, [%g3 + 0x00] ! out[i][0] = tx * len
fmuls %f5, %f13, %f5
st %f5, [%g3 + 0x04] ! out[i][1] = ty * len
fmuls %f7, %f13, %f7
st %f7, [%g3 + 0x08] ! out[i][2] = tz * len
cmp %o4, %g1 ! continue if (i < count)
bl 5b
add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
.globl _mesa_sparc_transform_normalize_normals_no_rot
_mesa_sparc_transform_normalize_normals_no_rot:
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
sethi %hi(ONE_DOT_ZERO), %g2
sub %sp, 16, %sp
st %g2, [%sp + STACK_VAR_OFF+0x0]
st %o1, [%sp + STACK_VAR_OFF+0x4]
ld [%sp + STACK_VAR_OFF+0x0], %f12 ! f12 = 1.0f
ld [%sp + STACK_VAR_OFF+0x4], %f15 ! f15 = scale
add %sp, 16, %sp
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
LDMATRIX_0_5_10(%o0)
/* dest->count = in->count */
st %g1, [%o4 + V4F_COUNT]
cmp %g1, 1
bl 7f
cmp %o3, 0
bne 4f
clr %o4 ! 'i' for STRIDE_LOOP
1: /* LENGTHS == NULL */
ld [%o5 + 0x00], %f0 ! ux = from[0]
ld [%o5 + 0x04], %f1 ! uy = from[1]
ld [%o5 + 0x08], %f2 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
/* tx (f3) = (ux * m0)
* ty (f5) = (uy * m5)
* tz (f7) = (uz * m10)
*/
fmuls %f0, M0, %f3 ! FGM Group
fmuls %f1, M5, %f5 ! FGM Group
fmuls %f2, M10, %f7 ! FGM Group
/* f3=tx, f5=ty, f7=tz */
/* len (f6) = (tx * tx) + (ty * ty) + (tz * tz) */
fmuls %f3, %f3, %f6 ! FGM Group stall, f3 available
fmuls %f5, %f5, %f8 ! FGM Group f5 available
fmuls %f7, %f7, %f10 ! FGM Group f7 available
fadds %f6, %f8, %f6 ! FGA Group 2cyc stall f6,f8 available
fadds %f6, %f10, %f6 ! FGA Group 4cyc stall f6,f10 available
/* scale (f6) = 1.0 / sqrt(len) */
fsqrts %f6, %f6 ! FDIV 20 cycles
fdivs %f12, %f6, %f6 ! FDIV 14 cycles
fmuls %f3, %f6, %f3
st %f3, [%g3 + 0x00] ! out[i][0] = tx * scale
fmuls %f5, %f6, %f5
st %f5, [%g3 + 0x04] ! out[i][1] = ty * scale
fmuls %f7, %f6, %f7
st %f7, [%g3 + 0x08] ! out[i][2] = tz * scale
cmp %o4, %g1 ! continue if (i < count)
bl 1b
add %g3, 0x10, %g3 ! advance out vector pointer
ba 7f
nop
4: /* LENGTHS != NULL */
fmuls M0, %f15, M0
fmuls M5, %f15, M5
fmuls M10, %f15, M10
5:
ld [%o5 + 0x00], %f0 ! ux = from[0]
ld [%o5 + 0x04], %f1 ! uy = from[1]
ld [%o5 + 0x08], %f2 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
/* tx (f3) = (ux * m0)
* ty (f5) = (uy * m5)
* tz (f7) = (uz * m10)
*/
fmuls %f0, M0, %f3 ! FGM Group
ld [%o3], %f13 ! LSU
fmuls %f1, M5, %f5 ! FGM Group
add %o3, 4, %o3 ! IEU0
fmuls %f2, M10, %f7 ! FGM Group
/* f3=tx, f5=ty, f7=tz, f13=lengths[i] */
fmuls %f3, %f13, %f3
st %f3, [%g3 + 0x00] ! out[i][0] = tx * len
fmuls %f5, %f13, %f5
st %f5, [%g3 + 0x04] ! out[i][1] = ty * len
fmuls %f7, %f13, %f7
st %f7, [%g3 + 0x08] ! out[i][2] = tz * len
cmp %o4, %g1 ! continue if (i < count)
bl 5b
add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
.globl _mesa_sparc_transform_rescale_normals_no_rot
_mesa_sparc_transform_rescale_normals_no_rot:
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
sub %sp, 16, %sp
st %o1, [%sp + STACK_VAR_OFF+0x0]
ld [%sp + STACK_VAR_OFF+0x0], %f15 ! f15 = scale
add %sp, 16, %sp
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
LDMATRIX_0_5_10(%o0)
/* dest->count = in->count */
st %g1, [%o4 + V4F_COUNT]
cmp %g1, 1
bl 7f
clr %o4 ! 'i' for STRIDE_LOOP
fmuls M0, %f15, M0
fmuls M5, %f15, M5
fmuls M10, %f15, M10
1: ld [%o5 + 0x00], %f0 ! ux = from[0]
ld [%o5 + 0x04], %f1 ! uy = from[1]
ld [%o5 + 0x08], %f2 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
/* tx (f3) = (ux * m0)
* ty (f5) = (uy * m5)
* tz (f7) = (uz * m10)
*/
fmuls %f0, M0, %f3 ! FGM Group
st %f3, [%g3 + 0x00] ! LSU
fmuls %f1, M5, %f5 ! FGM Group
st %f5, [%g3 + 0x04] ! LSU
fmuls %f2, M10, %f7 ! FGM Group
st %f7, [%g3 + 0x08] ! LSU
cmp %o4, %g1 ! continue if (i < count)
bl 1b
add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
.globl _mesa_sparc_transform_rescale_normals
_mesa_sparc_transform_rescale_normals:
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
sub %sp, 16, %sp
st %o1, [%sp + STACK_VAR_OFF+0x0]
ld [%sp + STACK_VAR_OFF+0x0], %f15 ! f15 = scale
add %sp, 16, %sp
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
LDMATRIX_0_1_2_4_5_6_8_9_10(%o0)
/* dest->count = in->count */
st %g1, [%o4 + V4F_COUNT]
cmp %g1, 1
bl 7f
clr %o4 ! 'i' for STRIDE_LOOP
fmuls M0, %f15, M0
fmuls M1, %f15, M1
fmuls M2, %f15, M2
fmuls M4, %f15, M4
fmuls M5, %f15, M5
fmuls M6, %f15, M6
fmuls M8, %f15, M8
fmuls M9, %f15, M9
fmuls M10, %f15, M10
1: ld [%o5 + 0x00], %f0 ! ux = from[0]
ld [%o5 + 0x04], %f1 ! uy = from[1]
ld [%o5 + 0x08], %f2 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
fmuls %f0, M0, %f3 ! FGM Group
fmuls %f1, M1, %f4 ! FGM Group
fmuls %f0, M4, %f5 ! FGM Group
fmuls %f1, M5, %f6 ! FGM Group
fmuls %f0, M8, %f7 ! FGM Group f3 available
fmuls %f1, M9, %f8 ! FGM Group f4 available
fadds %f3, %f4, %f3 ! FGA
fmuls %f2, M2, %f10 ! FGM Group f5 available
fmuls %f2, M6, %f0 ! FGM Group f6 available
fadds %f5, %f6, %f5 ! FGA
fmuls %f2, M10, %f4 ! FGM Group f7 available
fadds %f7, %f8, %f7 ! FGA Group f8,f3 available
fadds %f3, %f10, %f3 ! FGA Group f10 available
st %f3, [%g3 + 0x00] ! LSU
fadds %f5, %f0, %f5 ! FGA Group stall f0,f5 available
st %f5, [%g3 + 0x04] ! LSU
fadds %f7, %f4, %f7 ! FGA Group stall f4,f7 available
st %f7, [%g3 + 0x08] ! LSU
cmp %o4, %g1 ! continue if (i < count)
bl 1b
add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
.globl _mesa_sparc_transform_normals_no_rot
_mesa_sparc_transform_normals_no_rot:
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
LDMATRIX_0_5_10(%o0)
/* dest->count = in->count */
st %g1, [%o4 + V4F_COUNT]
cmp %g1, 1
bl 7f
clr %o4 ! 'i' for STRIDE_LOOP
1: ld [%o5 + 0x00], %f0 ! ux = from[0]
ld [%o5 + 0x04], %f1 ! uy = from[1]
ld [%o5 + 0x08], %f2 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
/* tx (f3) = (ux * m0)
* ty (f5) = (uy * m5)
* tz (f7) = (uz * m10)
*/
fmuls %f0, M0, %f3 ! FGM Group
st %f3, [%g3 + 0x00] ! LSU
fmuls %f1, M5, %f5 ! FGM Group
st %f5, [%g3 + 0x04] ! LSU
fmuls %f2, M10, %f7 ! FGM Group
st %f7, [%g3 + 0x08] ! LSU
cmp %o4, %g1 ! continue if (i < count)
bl 1b
add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
.globl _mesa_sparc_transform_normals
_mesa_sparc_transform_normals:
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
LDMATRIX_0_1_2_4_5_6_8_9_10(%o0)
/* dest->count = in->count */
st %g1, [%o4 + V4F_COUNT]
cmp %g1, 1
bl 7f
clr %o4 ! 'i' for STRIDE_LOOP
1: ld [%o5 + 0x00], %f0 ! ux = from[0]
ld [%o5 + 0x04], %f1 ! uy = from[1]
ld [%o5 + 0x08], %f2 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
fmuls %f0, M0, %f3 ! FGM Group
fmuls %f1, M1, %f4 ! FGM Group
fmuls %f0, M4, %f5 ! FGM Group
fmuls %f1, M5, %f6 ! FGM Group
fmuls %f0, M8, %f7 ! FGM Group f3 available
fmuls %f1, M9, %f8 ! FGM Group f4 available
fadds %f3, %f4, %f3 ! FGA
fmuls %f2, M2, %f10 ! FGM Group f5 available
fmuls %f2, M6, %f0 ! FGM Group f6 available
fadds %f5, %f6, %f5 ! FGA
fmuls %f2, M10, %f4 ! FGM Group f7 available
fadds %f7, %f8, %f7 ! FGA Group f8,f3 available
fadds %f3, %f10, %f3 ! FGA Group f10 available
st %f3, [%g3 + 0x00] ! LSU
fadds %f5, %f0, %f5 ! FGA Group stall f0,f5 available
st %f5, [%g3 + 0x04] ! LSU
fadds %f7, %f4, %f7 ! FGA Group stall f4,f7 available
st %f7, [%g3 + 0x08] ! LSU
cmp %o4, %g1 ! continue if (i < count)
bl 1b
add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
.globl _mesa_sparc_normalize_normals
_mesa_sparc_normalize_normals:
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
sethi %hi(ONE_DOT_ZERO), %g2
sub %sp, 16, %sp
st %g2, [%sp + STACK_VAR_OFF+0x0]
ld [%sp + STACK_VAR_OFF+0x0], %f12 ! f12 = 1.0f
add %sp, 16, %sp
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
/* dest->count = in->count */
st %g1, [%o4 + V4F_COUNT]
cmp %g1, 1
bl 7f
cmp %o3, 0
bne 4f
clr %o4 ! 'i' for STRIDE_LOOP
1: /* LENGTHS == NULL */
ld [%o5 + 0x00], %f3 ! ux = from[0]
ld [%o5 + 0x04], %f5 ! uy = from[1]
ld [%o5 + 0x08], %f7 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
/* f3=tx, f5=ty, f7=tz */
/* len (f6) = (tx * tx) + (ty * ty) + (tz * tz) */
fmuls %f3, %f3, %f6 ! FGM Group f3 available
fmuls %f5, %f5, %f8 ! FGM Group f5 available
fmuls %f7, %f7, %f10 ! FGM Group f7 available
fadds %f6, %f8, %f6 ! FGA Group 2cyc stall f6,f8 available
fadds %f6, %f10, %f6 ! FGA Group 4cyc stall f6,f10 available
/* scale (f6) = 1.0 / sqrt(len) */
fsqrts %f6, %f6 ! FDIV 20 cycles
fdivs %f12, %f6, %f6 ! FDIV 14 cycles
fmuls %f3, %f6, %f3
st %f3, [%g3 + 0x00] ! out[i][0] = tx * scale
fmuls %f5, %f6, %f5
st %f5, [%g3 + 0x04] ! out[i][1] = ty * scale
fmuls %f7, %f6, %f7
st %f7, [%g3 + 0x08] ! out[i][2] = tz * scale
cmp %o4, %g1 ! continue if (i < count)
bl 1b
add %g3, 0x10, %g3 ! advance out vector pointer
ba 7f
nop
4: /* LENGTHS != NULL */
5:
ld [%o5 + 0x00], %f3 ! ux = from[0]
ld [%o5 + 0x04], %f5 ! uy = from[1]
ld [%o5 + 0x08], %f7 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
ld [%o3], %f13 ! LSU
add %o3, 4, %o3 ! IEU0
/* f3=tx, f5=ty, f7=tz, f13=lengths[i] */
fmuls %f3, %f13, %f3
st %f3, [%g3 + 0x00] ! out[i][0] = tx * len
fmuls %f5, %f13, %f5
st %f5, [%g3 + 0x04] ! out[i][1] = ty * len
fmuls %f7, %f13, %f7
st %f7, [%g3 + 0x08] ! out[i][2] = tz * len
cmp %o4, %g1 ! continue if (i < count)
bl 5b
add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop
.globl _mesa_sparc_rescale_normals
_mesa_sparc_rescale_normals:
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
sethi %hi(ONE_DOT_ZERO), %g2
sub %sp, 16, %sp
st %o1, [%sp + STACK_VAR_OFF+0x0]
ld [%sp + STACK_VAR_OFF+0x0], %f15 ! f15 = scale
add %sp, 16, %sp
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
/* dest->count = in->count */
st %g1, [%o4 + V4F_COUNT]
cmp %g1, 1
bl 7f
clr %o4 ! 'i' for STRIDE_LOOP
1:
ld [%o5 + 0x00], %f3 ! ux = from[0]
ld [%o5 + 0x04], %f5 ! uy = from[1]
ld [%o5 + 0x08], %f7 ! uz = from[2]
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
add %o4, 1, %o4 ! i++
/* f3=tx, f5=ty, f7=tz */
fmuls %f3, %f15, %f3
st %f3, [%g3 + 0x00] ! out[i][0] = tx * scale
fmuls %f5, %f15, %f5
st %f5, [%g3 + 0x04] ! out[i][1] = ty * scale
fmuls %f7, %f15, %f7
st %f7, [%g3 + 0x08] ! out[i][2] = tz * scale
cmp %o4, %g1 ! continue if (i < count)
bl 1b
add %g3, 0x10, %g3 ! advance out vector pointer
7: retl
nop

View File

@ -1,142 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Sparc assembly code by David S. Miller
*/
#include "sparc.h"
#ifdef USE_SPARC_ASM
#include "main/context.h"
#include "math/m_xform.h"
#include "tnl/t_context.h"
#ifdef DEBUG
#include "math/m_debug.h"
#endif
#define XFORM_ARGS GLvector4f *to_vec, \
const GLfloat m[16], \
const GLvector4f *from_vec
#define DECLARE_XFORM_GROUP(pfx, sz) \
extern void _mesa_##pfx##_transform_points##sz##_general(XFORM_ARGS); \
extern void _mesa_##pfx##_transform_points##sz##_identity(XFORM_ARGS); \
extern void _mesa_##pfx##_transform_points##sz##_3d_no_rot(XFORM_ARGS); \
extern void _mesa_##pfx##_transform_points##sz##_perspective(XFORM_ARGS); \
extern void _mesa_##pfx##_transform_points##sz##_2d(XFORM_ARGS); \
extern void _mesa_##pfx##_transform_points##sz##_2d_no_rot(XFORM_ARGS); \
extern void _mesa_##pfx##_transform_points##sz##_3d(XFORM_ARGS);
#define ASSIGN_XFORM_GROUP(pfx, sz) \
_mesa_transform_tab[sz][MATRIX_GENERAL] = \
_mesa_##pfx##_transform_points##sz##_general; \
_mesa_transform_tab[sz][MATRIX_IDENTITY] = \
_mesa_##pfx##_transform_points##sz##_identity; \
_mesa_transform_tab[sz][MATRIX_3D_NO_ROT] = \
_mesa_##pfx##_transform_points##sz##_3d_no_rot; \
_mesa_transform_tab[sz][MATRIX_PERSPECTIVE] = \
_mesa_##pfx##_transform_points##sz##_perspective; \
_mesa_transform_tab[sz][MATRIX_2D] = \
_mesa_##pfx##_transform_points##sz##_2d; \
_mesa_transform_tab[sz][MATRIX_2D_NO_ROT] = \
_mesa_##pfx##_transform_points##sz##_2d_no_rot; \
_mesa_transform_tab[sz][MATRIX_3D] = \
_mesa_##pfx##_transform_points##sz##_3d;
DECLARE_XFORM_GROUP(sparc, 1)
DECLARE_XFORM_GROUP(sparc, 2)
DECLARE_XFORM_GROUP(sparc, 3)
DECLARE_XFORM_GROUP(sparc, 4)
extern GLvector4f *_mesa_sparc_cliptest_points4(GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask,
GLboolean viewport_z_clip);
extern GLvector4f *_mesa_sparc_cliptest_points4_np(GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask,
GLboolean viewport_z_clip);
#define NORM_ARGS const GLmatrix *mat, \
GLfloat scale, \
const GLvector4f *in, \
const GLfloat *lengths, \
GLvector4f *dest
extern void _mesa_sparc_transform_normalize_normals(NORM_ARGS);
extern void _mesa_sparc_transform_normalize_normals_no_rot(NORM_ARGS);
extern void _mesa_sparc_transform_rescale_normals_no_rot(NORM_ARGS);
extern void _mesa_sparc_transform_rescale_normals(NORM_ARGS);
extern void _mesa_sparc_transform_normals_no_rot(NORM_ARGS);
extern void _mesa_sparc_transform_normals(NORM_ARGS);
extern void _mesa_sparc_normalize_normals(NORM_ARGS);
extern void _mesa_sparc_rescale_normals(NORM_ARGS);
void _mesa_init_all_sparc_transform_asm(void)
{
ASSIGN_XFORM_GROUP(sparc, 1)
ASSIGN_XFORM_GROUP(sparc, 2)
ASSIGN_XFORM_GROUP(sparc, 3)
ASSIGN_XFORM_GROUP(sparc, 4)
_mesa_clip_tab[4] = _mesa_sparc_cliptest_points4;
_mesa_clip_np_tab[4] = _mesa_sparc_cliptest_points4_np;
_mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
_mesa_sparc_transform_normalize_normals;
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
_mesa_sparc_transform_normalize_normals_no_rot;
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
_mesa_sparc_transform_rescale_normals_no_rot;
_mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
_mesa_sparc_transform_rescale_normals;
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
_mesa_sparc_transform_normals_no_rot;
_mesa_normal_tab[NORM_TRANSFORM] =
_mesa_sparc_transform_normals;
_mesa_normal_tab[NORM_NORMALIZE] =
_mesa_sparc_normalize_normals;
_mesa_normal_tab[NORM_RESCALE] =
_mesa_sparc_rescale_normals;
#ifdef DEBUG_MATH
_math_test_all_transform_functions("sparc");
_math_test_all_cliptest_functions("sparc");
_math_test_all_normal_transform_functions("sparc");
#endif
}
#endif /* USE_SPARC_ASM */

View File

@ -1,36 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Sparc assembly code by David S. Miller
*/
#ifndef SPARC_H
#define SPARC_H
extern void _mesa_init_all_sparc_transform_asm(void);
#endif /* !(SPARC_H) */

View File

@ -1,220 +0,0 @@
/*
* Clip testing in SPARC assembly
*/
#if __arch64__
#define LDPTR ldx
#define MATH_ASM_PTR_SIZE 8
#include "math/m_vector_asm.h"
#else
#define LDPTR ld
#define MATH_ASM_PTR_SIZE 4
#include "math/m_vector_asm.h"
#endif
.register %g2, #scratch
.register %g3, #scratch
.text
.align 64
one_dot_zero:
.word 0x3f800000 /* 1.0f */
/* This trick is shamelessly stolen from the x86
* Mesa asm. Very clever, and we can do it too
* since we have the necessary add with carry
* instructions on Sparc.
*/
clip_table:
.byte 0, 1, 0, 2, 4, 5, 4, 6
.byte 0, 1, 0, 2, 8, 9, 8, 10
.byte 32, 33, 32, 34, 36, 37, 36, 38
.byte 32, 33, 32, 34, 40, 41, 40, 42
.byte 0, 1, 0, 2, 4, 5, 4, 6
.byte 0, 1, 0, 2, 8, 9, 8, 10
.byte 16, 17, 16, 18, 20, 21, 20, 22
.byte 16, 17, 16, 18, 24, 25, 24, 26
.byte 63, 61, 63, 62, 55, 53, 55, 54
.byte 63, 61, 63, 62, 59, 57, 59, 58
.byte 47, 45, 47, 46, 39, 37, 39, 38
.byte 47, 45, 47, 46, 43, 41, 43, 42
.byte 63, 61, 63, 62, 55, 53, 55, 54
.byte 63, 61, 63, 62, 59, 57, 59, 58
.byte 31, 29, 31, 30, 23, 21, 23, 22
.byte 31, 29, 31, 30, 27, 25, 27, 26
/* GLvector4f *clip_vec, GLvector4f *proj_vec,
GLubyte clipMask[], GLubyte *orMask, GLubyte *andMask,
GLboolean viewport_z_enable */
.align 64
__pc_tramp:
retl
nop
.globl _mesa_sparc_cliptest_points4
_mesa_sparc_cliptest_points4:
save %sp, -64, %sp
call __pc_tramp
sub %o7, (. - one_dot_zero - 4), %g1
ld [%g1 + 0x0], %f4
add %g1, 0x4, %g1
ld [%i0 + V4F_STRIDE], %l1
ld [%i0 + V4F_COUNT], %l3
LDPTR [%i0 + V4F_START], %i0
LDPTR [%i1 + V4F_START], %i5
ldub [%i3], %g2
ldub [%i4], %g3
sll %g3, 8, %g3
or %g2, %g3, %g2
ld [%i1 + V4F_FLAGS], %g3
or %g3, VEC_SIZE_4, %g3
st %g3, [%i1 + V4F_FLAGS]
mov 3, %g3
st %g3, [%i1 + V4F_SIZE]
st %l3, [%i1 + V4F_COUNT]
clr %l2
clr %l0
/* l0: i
* l3: count
* l1: stride
* l2: c
* g2: (tmpAndMask << 8) | tmpOrMask
* g1: clip_table
* i0: from[stride][i]
* i2: clipMask
* i5: vProj[4][i]
*/
1: ld [%i0 + 0x0c], %f3 ! LSU Group
ld [%i0 + 0x0c], %g5 ! LSU Group
ld [%i0 + 0x08], %g4 ! LSU Group
fdivs %f4, %f3, %f8 ! FGM
addcc %g5, %g5, %g5 ! IEU1 Group
addx %g0, 0x0, %g3 ! IEU1 Group
addcc %g4, %g4, %g4 ! IEU1 Group
addx %g3, %g3, %g3 ! IEU1 Group
subcc %g5, %g4, %g0 ! IEU1 Group
ld [%i0 + 0x04], %g4 ! LSU Group
addx %g3, %g3, %g3 ! IEU1 Group
addcc %g4, %g4, %g4 ! IEU1 Group
addx %g3, %g3, %g3 ! IEU1 Group
subcc %g5, %g4, %g0 ! IEU1 Group
ld [%i0 + 0x00], %g4 ! LSU Group
addx %g3, %g3, %g3 ! IEU1 Group
addcc %g4, %g4, %g4 ! IEU1 Group
addx %g3, %g3, %g3 ! IEU1 Group
subcc %g5, %g4, %g0 ! IEU1 Group
addx %g3, %g3, %g3 ! IEU1 Group
ldub [%g1 + %g3], %g3 ! LSU Group
cmp %g3, 0 ! IEU1 Group, stall
be 2f ! CTI
stb %g3, [%i2] ! LSU
sll %g3, 8, %g4 ! IEU1 Group
add %l2, 1, %l2 ! IEU0
st %g0, [%i5 + 0x00] ! LSU
or %g4, 0xff, %g4 ! IEU0 Group
or %g2, %g3, %g2 ! IEU1
st %g0, [%i5 + 0x04] ! LSU
and %g2, %g4, %g2 ! IEU0 Group
st %g0, [%i5 + 0x08] ! LSU
b 3f ! CTI
st %f4, [%i5 + 0x0c] ! LSU Group
2: ld [%i0 + 0x00], %f0 ! LSU Group
ld [%i0 + 0x04], %f1 ! LSU Group
ld [%i0 + 0x08], %f2 ! LSU Group
fmuls %f0, %f8, %f0 ! FGM
st %f0, [%i5 + 0x00] ! LSU Group
fmuls %f1, %f8, %f1 ! FGM
st %f1, [%i5 + 0x04] ! LSU Group
fmuls %f2, %f8, %f2 ! FGM
st %f2, [%i5 + 0x08] ! LSU Group
st %f8, [%i5 + 0x0c] ! LSU Group
3: add %i5, 0x10, %i5 ! IEU1
add %l0, 1, %l0 ! IEU0 Group
add %i2, 1, %i2 ! IEU0 Group
cmp %l0, %l3 ! IEU1 Group
bne 1b ! CTI
add %i0, %l1, %i0 ! IEU0 Group
stb %g2, [%i3] ! LSU
srl %g2, 8, %g3 ! IEU0 Group
cmp %l2, %l3 ! IEU1 Group
bl,a 1f ! CTI
clr %g3 ! IEU0
1: stb %g3, [%i4] ! LSU Group
ret ! CTI Group
restore %i1, 0x0, %o0
.globl _mesa_sparc_cliptest_points4_np
_mesa_sparc_cliptest_points4_np:
save %sp, -64, %sp
call __pc_tramp
sub %o7, (. - one_dot_zero - 4), %g1
add %g1, 0x4, %g1
ld [%i0 + V4F_STRIDE], %l1
ld [%i0 + V4F_COUNT], %l3
LDPTR [%i0 + V4F_START], %i0
ldub [%i3], %g2
ldub [%i4], %g3
sll %g3, 8, %g3
or %g2, %g3, %g2
clr %l2
clr %l0
/* l0: i
* l3: count
* l1: stride
* l2: c
* g2: (tmpAndMask << 8) | tmpOrMask
* g1: clip_table
* i0: from[stride][i]
* i2: clipMask
*/
1: ld [%i0 + 0x0c], %g5 ! LSU Group
ld [%i0 + 0x08], %g4 ! LSU Group
addcc %g5, %g5, %g5 ! IEU1 Group
addx %g0, 0x0, %g3 ! IEU1 Group
addcc %g4, %g4, %g4 ! IEU1 Group
addx %g3, %g3, %g3 ! IEU1 Group
subcc %g5, %g4, %g0 ! IEU1 Group
ld [%i0 + 0x04], %g4 ! LSU Group
addx %g3, %g3, %g3 ! IEU1 Group
addcc %g4, %g4, %g4 ! IEU1 Group
addx %g3, %g3, %g3 ! IEU1 Group
subcc %g5, %g4, %g0 ! IEU1 Group
ld [%i0 + 0x00], %g4 ! LSU Group
addx %g3, %g3, %g3 ! IEU1 Group
addcc %g4, %g4, %g4 ! IEU1 Group
addx %g3, %g3, %g3 ! IEU1 Group
subcc %g5, %g4, %g0 ! IEU1 Group
addx %g3, %g3, %g3 ! IEU1 Group
ldub [%g1 + %g3], %g3 ! LSU Group
cmp %g3, 0 ! IEU1 Group, stall
be 2f ! CTI
stb %g3, [%i2] ! LSU
sll %g3, 8, %g4 ! IEU1 Group
add %l2, 1, %l2 ! IEU0
or %g4, 0xff, %g4 ! IEU0 Group
or %g2, %g3, %g2 ! IEU1
and %g2, %g4, %g2 ! IEU0 Group
2: add %l0, 1, %l0 ! IEU0 Group
add %i2, 1, %i2 ! IEU0 Group
cmp %l0, %l3 ! IEU1 Group
bne 1b ! CTI
add %i0, %l1, %i0 ! IEU0 Group
stb %g2, [%i3] ! LSU
srl %g2, 8, %g3 ! IEU0 Group
cmp %l2, %l3 ! IEU1 Group
bl,a 1f ! CTI
clr %g3 ! IEU0
1: stb %g3, [%i4] ! LSU Group
ret ! CTI Group
restore %i1, 0x0, %o0

View File

@ -1,153 +0,0 @@
/*
* SPARC assembly matrix code.
*/
#ifndef _SPARC_MATRIX_H
#define _SPARC_MATRIX_H
#ifdef __arch64__
#define LDPTR ldx
#define MATH_ASM_PTR_SIZE 8
#include "math/m_vector_asm.h"
#else
#define LDPTR ld
#define MATH_ASM_PTR_SIZE 4
#include "math/m_vector_asm.h"
#endif
#define M0 %f16
#define M1 %f17
#define M2 %f18
#define M3 %f19
#define M4 %f20
#define M5 %f21
#define M6 %f22
#define M7 %f23
#define M8 %f24
#define M9 %f25
#define M10 %f26
#define M11 %f27
#define M12 %f28
#define M13 %f29
#define M14 %f30
#define M15 %f31
#define LDMATRIX_0_1_2_3_12_13_14_15(BASE) \
ldd [BASE + ( 0 * 0x4)], M0; \
ldd [BASE + ( 2 * 0x4)], M2; \
ldd [BASE + (12 * 0x4)], M12; \
ldd [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_1_12_13(BASE) \
ldd [BASE + ( 0 * 0x4)], M0; \
ldd [BASE + (12 * 0x4)], M12
#define LDMATRIX_0_12_13(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ldd [BASE + (12 * 0x4)], M12
#define LDMATRIX_0_1_2_12_13_14(BASE) \
ldd [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 2 * 0x4)], M2; \
ldd [BASE + (12 * 0x4)], M12; \
ld [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_12_13_14(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ldd [BASE + (12 * 0x4)], M12; \
ld [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_14(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ld [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_1_2_3_4_5_6_7_12_13_14_15(BASE) \
ldd [BASE + ( 0 * 0x4)], M0; \
ldd [BASE + ( 2 * 0x4)], M2; \
ldd [BASE + ( 4 * 0x4)], M4; \
ldd [BASE + ( 6 * 0x4)], M6; \
ldd [BASE + (12 * 0x4)], M12; \
ldd [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_5_12_13(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 5 * 0x4)], M5; \
ldd [BASE + (12 * 0x4)], M12
#define LDMATRIX_0_1_2_3_4_5_6_12_13_14(BASE) \
ldd [BASE + ( 0 * 0x4)], M0; \
ldd [BASE + ( 2 * 0x4)], M2; \
ldd [BASE + ( 4 * 0x4)], M4; \
ld [BASE + ( 6 * 0x4)], M6; \
ldd [BASE + (12 * 0x4)], M12; \
ld [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_5_12_13_14(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 5 * 0x4)], M5; \
ldd [BASE + (12 * 0x4)], M12; \
ld [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_5_14(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 5 * 0x4)], M5; \
ld [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15(BASE) \
ldd [BASE + ( 0 * 0x4)], M0; \
ldd [BASE + ( 2 * 0x4)], M2; \
ldd [BASE + ( 4 * 0x4)], M4; \
ldd [BASE + ( 6 * 0x4)], M6; \
ldd [BASE + ( 8 * 0x4)], M8; \
ldd [BASE + (10 * 0x4)], M10; \
ldd [BASE + (12 * 0x4)], M12; \
ldd [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_1_4_5_12_13(BASE) \
ldd [BASE + ( 0 * 0x4)], M0; \
ldd [BASE + ( 4 * 0x4)], M4; \
ldd [BASE + (12 * 0x4)], M12
#define LDMATRIX_0_5_12_13(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 5 * 0x4)], M5; \
ldd [BASE + (12 * 0x4)], M12
#define LDMATRIX_0_1_2_4_5_6_8_9_10(BASE) \
ldd [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 2 * 0x4)], M2; \
ldd [BASE + ( 4 * 0x4)], M4; \
ld [BASE + ( 6 * 0x4)], M6; \
ldd [BASE + ( 8 * 0x4)], M8; \
ld [BASE + (10 * 0x4)], M10
#define LDMATRIX_0_1_2_4_5_6_8_9_10_12_13_14(BASE) \
ldd [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 2 * 0x4)], M2; \
ldd [BASE + ( 4 * 0x4)], M4; \
ld [BASE + ( 6 * 0x4)], M6; \
ldd [BASE + ( 8 * 0x4)], M8; \
ld [BASE + (10 * 0x4)], M10; \
ldd [BASE + (12 * 0x4)], M12; \
ld [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_5_10(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 5 * 0x4)], M5; \
ld [BASE + (10 * 0x4)], M10;
#define LDMATRIX_0_5_10_12_13_14(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 5 * 0x4)], M5; \
ld [BASE + (10 * 0x4)], M10; \
ldd [BASE + (12 * 0x4)], M12; \
ld [BASE + (14 * 0x4)], M14
#define LDMATRIX_0_5_8_9_10_14(BASE) \
ld [BASE + ( 0 * 0x4)], M0; \
ld [BASE + ( 5 * 0x4)], M5; \
ldd [BASE + ( 8 * 0x4)], M8; \
ld [BASE + (10 * 0x4)], M10; \
ld [BASE + (14 * 0x4)], M14
#endif /* !(_SPARC_MATRIX_H) */

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +0,0 @@
INTRODUCTION
Mesa's native software rasterizer. This module provides the fallback
paths for rasterization operations and states that aren't accelerated
in hardware drivers, and as the full rasterization engine in software
drivers.
The swrast module 'stands alone', relying only on interfaces to core
mesa and it's own driver interface. It knows nothing about the tnl or
other modules, allowing it to be used for fallback paths in future tnl
schemes without modification.
As well as providing triangle/line/point rasterization functionality,
the module provides implementations of the pixel operations
(ReadPixels, etc), and texture operations (CopyTexSubImage) which may
be plugged in to the core Mesa driver interface where accelerated
versions of these operations are unavailable.
STATE
To create and destroy the module:
GLboolean _swrast_CreateContext( struct gl_context *ctx );
void _swrast_DestroyContext( struct gl_context *ctx );
This module tracks state changes internally and maintains derived
values based on the current state. For this to work, the driver
ensure the following funciton is called whenever the state changes and
the swsetup module is 'awake':
void _swrast_InvalidateState( struct gl_context *ctx, GLuint new_state );
There is no explicit call to put the swrast module to sleep.
CUSTOMIZATION
void (*choose_point)( struct gl_context * );
void (*choose_line)( struct gl_context * );
void (*choose_triangle)( struct gl_context * );
Drivers may add additional triangle/line/point functions to swrast by
overriding these functions. It is necessary for the driver to be very
careful that it doesn't return an inappropriate function, eg a
rasterization function in feedback mode. See the X11 driver for
examples.
DRIVER INTERFACE
The swrast device driver provides swrast primarily with span- and
pixel- level interfaces to a framebuffer, with a few additional hooks
for locking and setting the read buffer.
See the definition of struct swrast_device_driver in swrast.h.

View File

@ -1,493 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "c99_math.h"
#include "main/glheader.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/teximage.h"
#include "swrast/s_aaline.h"
#include "swrast/s_context.h"
#include "swrast/s_span.h"
#include "swrast/swrast.h"
#define SUB_PIXEL 4
/*
* Info about the AA line we're rendering
*/
struct LineInfo
{
GLfloat x0, y0; /* start */
GLfloat x1, y1; /* end */
GLfloat dx, dy; /* direction vector */
GLfloat len; /* length */
GLfloat halfWidth; /* half of line width */
GLfloat xAdj, yAdj; /* X and Y adjustment for quad corners around line */
/* for coverage computation */
GLfloat qx0, qy0; /* quad vertices */
GLfloat qx1, qy1;
GLfloat qx2, qy2;
GLfloat qx3, qy3;
GLfloat ex0, ey0; /* quad edge vectors */
GLfloat ex1, ey1;
GLfloat ex2, ey2;
GLfloat ex3, ey3;
/* DO_Z */
GLfloat zPlane[4];
/* DO_RGBA - always enabled */
GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
/* DO_ATTRIBS */
GLfloat wPlane[4];
GLfloat attrPlane[VARYING_SLOT_MAX][4][4];
GLfloat lambda[VARYING_SLOT_MAX];
GLfloat texWidth[VARYING_SLOT_MAX];
GLfloat texHeight[VARYING_SLOT_MAX];
SWspan span;
};
/*
* Compute the equation of a plane used to interpolate line fragment data
* such as color, Z, texture coords, etc.
* Input: (x0, y0) and (x1,y1) are the endpoints of the line.
* z0, and z1 are the end point values to interpolate.
* Output: plane - the plane equation.
*
* Note: we don't really have enough parameters to specify a plane.
* We take the endpoints of the line and compute a plane such that
* the cross product of the line vector and the plane normal is
* parallel to the projection plane.
*/
static void
compute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
GLfloat z0, GLfloat z1, GLfloat plane[4])
{
#if 0
/* original */
const GLfloat px = x1 - x0;
const GLfloat py = y1 - y0;
const GLfloat pz = z1 - z0;
const GLfloat qx = -py;
const GLfloat qy = px;
const GLfloat qz = 0;
const GLfloat a = py * qz - pz * qy;
const GLfloat b = pz * qx - px * qz;
const GLfloat c = px * qy - py * qx;
const GLfloat d = -(a * x0 + b * y0 + c * z0);
plane[0] = a;
plane[1] = b;
plane[2] = c;
plane[3] = d;
#else
/* simplified */
const GLfloat px = x1 - x0;
const GLfloat py = y1 - y0;
const GLfloat pz = z0 - z1;
const GLfloat a = pz * px;
const GLfloat b = pz * py;
const GLfloat c = px * px + py * py;
const GLfloat d = -(a * x0 + b * y0 + c * z0);
if (a == 0.0F && b == 0.0F && c == 0.0F && d == 0.0F) {
plane[0] = 0.0F;
plane[1] = 0.0F;
plane[2] = 1.0F;
plane[3] = 0.0F;
}
else {
plane[0] = a;
plane[1] = b;
plane[2] = c;
plane[3] = d;
}
#endif
}
static inline void
constant_plane(GLfloat value, GLfloat plane[4])
{
plane[0] = 0.0F;
plane[1] = 0.0F;
plane[2] = -1.0F;
plane[3] = value;
}
static inline GLfloat
solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
{
const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
return z;
}
#define SOLVE_PLANE(X, Y, PLANE) \
((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2])
/*
* Return 1 / solve_plane().
*/
static inline GLfloat
solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4])
{
const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y;
if (denom == 0.0F)
return 0.0F;
else
return -plane[2] / denom;
}
/*
* Solve plane and return clamped GLchan value.
*/
static inline GLchan
solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4])
{
const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
#if CHAN_TYPE == GL_FLOAT
return CLAMP(z, 0.0F, CHAN_MAXF);
#else
if (z < 0)
return 0;
else if (z > CHAN_MAX)
return CHAN_MAX;
return (GLchan) lroundf(z);
#endif
}
/*
* Compute mipmap level of detail.
*/
static inline GLfloat
compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4],
GLfloat invQ, GLfloat width, GLfloat height)
{
GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width;
GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width;
GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height;
GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height;
GLfloat r1 = dudx * dudx + dudy * dudy;
GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
GLfloat rho2 = r1 + r2;
/* return log base 2 of rho */
if (rho2 == 0.0F)
return 0.0;
else
return logf(rho2) * 1.442695f * 0.5f;/* 1.442695 = 1/log(2) */
}
/*
* Fill in the samples[] array with the (x,y) subpixel positions of
* xSamples * ySamples sample positions.
* Note that the four corner samples are put into the first four
* positions of the array. This allows us to optimize for the common
* case of all samples being inside the polygon.
*/
static void
make_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2])
{
const GLfloat dx = 1.0F / (GLfloat) xSamples;
const GLfloat dy = 1.0F / (GLfloat) ySamples;
GLint x, y;
GLint i;
i = 4;
for (x = 0; x < xSamples; x++) {
for (y = 0; y < ySamples; y++) {
GLint j;
if (x == 0 && y == 0) {
/* lower left */
j = 0;
}
else if (x == xSamples - 1 && y == 0) {
/* lower right */
j = 1;
}
else if (x == 0 && y == ySamples - 1) {
/* upper left */
j = 2;
}
else if (x == xSamples - 1 && y == ySamples - 1) {
/* upper right */
j = 3;
}
else {
j = i++;
}
samples[j][0] = x * dx + 0.5F * dx;
samples[j][1] = y * dy + 0.5F * dy;
}
}
}
/*
* Compute how much of the given pixel's area is inside the rectangle
* defined by vertices v0, v1, v2, v3.
* Vertices MUST be specified in counter-clockwise order.
* Return: coverage in [0, 1].
*/
static GLfloat
compute_coveragef(const struct LineInfo *info,
GLint winx, GLint winy)
{
static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2];
static GLboolean haveSamples = GL_FALSE;
const GLfloat x = (GLfloat) winx;
const GLfloat y = (GLfloat) winy;
GLint stop = 4, i;
GLfloat insideCount = SUB_PIXEL * SUB_PIXEL;
if (!haveSamples) {
make_sample_table(SUB_PIXEL, SUB_PIXEL, samples);
haveSamples = GL_TRUE;
}
#if 0 /*DEBUG*/
{
const GLfloat area = dx0 * dy1 - dx1 * dy0;
assert(area >= 0.0);
}
#endif
for (i = 0; i < stop; i++) {
const GLfloat sx = x + samples[i][0];
const GLfloat sy = y + samples[i][1];
const GLfloat fx0 = sx - info->qx0;
const GLfloat fy0 = sy - info->qy0;
const GLfloat fx1 = sx - info->qx1;
const GLfloat fy1 = sy - info->qy1;
const GLfloat fx2 = sx - info->qx2;
const GLfloat fy2 = sy - info->qy2;
const GLfloat fx3 = sx - info->qx3;
const GLfloat fy3 = sy - info->qy3;
/* cross product determines if sample is inside or outside each edge */
GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0);
GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1);
GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2);
GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3);
/* Check if the sample is exactly on an edge. If so, let cross be a
* positive or negative value depending on the direction of the edge.
*/
if (cross0 == 0.0F)
cross0 = info->ex0 + info->ey0;
if (cross1 == 0.0F)
cross1 = info->ex1 + info->ey1;
if (cross2 == 0.0F)
cross2 = info->ex2 + info->ey2;
if (cross3 == 0.0F)
cross3 = info->ex3 + info->ey3;
if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) {
/* point is outside quadrilateral */
insideCount -= 1.0F;
stop = SUB_PIXEL * SUB_PIXEL;
}
}
if (stop == 4)
return 1.0F;
else
return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL));
}
typedef void (*plot_func)(struct gl_context *ctx, struct LineInfo *line,
int ix, int iy);
/*
* Draw an AA line segment (called many times per line when stippling)
*/
static void
segment(struct gl_context *ctx,
struct LineInfo *line,
plot_func plot,
GLfloat t0, GLfloat t1)
{
const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx;
const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy;
/* compute the actual segment's endpoints */
const GLfloat x0 = line->x0 + t0 * line->dx;
const GLfloat y0 = line->y0 + t0 * line->dy;
const GLfloat x1 = line->x0 + t1 * line->dx;
const GLfloat y1 = line->y0 + t1 * line->dy;
/* compute vertices of the line-aligned quadrilateral */
line->qx0 = x0 - line->yAdj;
line->qy0 = y0 + line->xAdj;
line->qx1 = x0 + line->yAdj;
line->qy1 = y0 - line->xAdj;
line->qx2 = x1 + line->yAdj;
line->qy2 = y1 - line->xAdj;
line->qx3 = x1 - line->yAdj;
line->qy3 = y1 + line->xAdj;
/* compute the quad's edge vectors (for coverage calc) */
line->ex0 = line->qx1 - line->qx0;
line->ey0 = line->qy1 - line->qy0;
line->ex1 = line->qx2 - line->qx1;
line->ey1 = line->qy2 - line->qy1;
line->ex2 = line->qx3 - line->qx2;
line->ey2 = line->qy3 - line->qy2;
line->ex3 = line->qx0 - line->qx3;
line->ey3 = line->qy0 - line->qy3;
if (absDx > absDy) {
/* X-major line */
GLfloat dydx = line->dy / line->dx;
GLfloat xLeft, xRight, yBot, yTop;
GLint ix, ixRight;
if (x0 < x1) {
xLeft = x0 - line->halfWidth;
xRight = x1 + line->halfWidth;
if (line->dy >= 0.0F) {
yBot = y0 - 3.0F * line->halfWidth;
yTop = y0 + line->halfWidth;
}
else {
yBot = y0 - line->halfWidth;
yTop = y0 + 3.0F * line->halfWidth;
}
}
else {
xLeft = x1 - line->halfWidth;
xRight = x0 + line->halfWidth;
if (line->dy <= 0.0F) {
yBot = y1 - 3.0F * line->halfWidth;
yTop = y1 + line->halfWidth;
}
else {
yBot = y1 - line->halfWidth;
yTop = y1 + 3.0F * line->halfWidth;
}
}
/* scan along the line, left-to-right */
ixRight = (GLint) (xRight + 1.0F);
/*printf("avg span height: %g\n", yTop - yBot);*/
for (ix = (GLint) xLeft; ix < ixRight; ix++) {
const GLint iyBot = (GLint) yBot;
const GLint iyTop = (GLint) (yTop + 1.0F);
GLint iy;
/* scan across the line, bottom-to-top */
for (iy = iyBot; iy < iyTop; iy++) {
plot(ctx, line, ix, iy);
}
yBot += dydx;
yTop += dydx;
}
}
else {
/* Y-major line */
GLfloat dxdy = line->dx / line->dy;
GLfloat yBot, yTop, xLeft, xRight;
GLint iy, iyTop;
if (y0 < y1) {
yBot = y0 - line->halfWidth;
yTop = y1 + line->halfWidth;
if (line->dx >= 0.0F) {
xLeft = x0 - 3.0F * line->halfWidth;
xRight = x0 + line->halfWidth;
}
else {
xLeft = x0 - line->halfWidth;
xRight = x0 + 3.0F * line->halfWidth;
}
}
else {
yBot = y1 - line->halfWidth;
yTop = y0 + line->halfWidth;
if (line->dx <= 0.0F) {
xLeft = x1 - 3.0F * line->halfWidth;
xRight = x1 + line->halfWidth;
}
else {
xLeft = x1 - line->halfWidth;
xRight = x1 + 3.0F * line->halfWidth;
}
}
/* scan along the line, bottom-to-top */
iyTop = (GLint) (yTop + 1.0F);
/*printf("avg span width: %g\n", xRight - xLeft);*/
for (iy = (GLint) yBot; iy < iyTop; iy++) {
const GLint ixLeft = (GLint) xLeft;
const GLint ixRight = (GLint) (xRight + 1.0F);
GLint ix;
/* scan across the line, left-to-right */
for (ix = ixLeft; ix < ixRight; ix++) {
plot(ctx, line, ix, iy);
}
xLeft += dxdy;
xRight += dxdy;
}
}
}
#define NAME(x) aa_rgba_##x
#define DO_Z
#include "s_aalinetemp.h"
#define NAME(x) aa_general_rgba_##x
#define DO_Z
#define DO_ATTRIBS
#include "s_aalinetemp.h"
void
_swrast_choose_aa_line_function(struct gl_context *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
assert(ctx->Line.SmoothFlag);
if (ctx->Texture._EnabledCoordUnits != 0
|| _swrast_use_fragment_program(ctx)
|| (ctx->Light.Enabled &&
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
|| ctx->Fog.ColorSumEnabled
|| swrast->_FogEnabled) {
swrast->Line = aa_general_rgba_line;
}
else {
swrast->Line = aa_rgba_line;
}
}

View File

@ -1,38 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_AALINE_H
#define S_AALINE_H
struct gl_context;
extern void
_swrast_choose_aa_line_function(struct gl_context *ctx);
#endif

View File

@ -1,245 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Antialiased line template.
*/
/*
* Function to render each fragment in the AA line.
* \param ix - integer fragment window X coordiante
* \param iy - integer fragment window Y coordiante
*/
static void
NAME(plot)(struct gl_context *ctx, struct LineInfo *line, int ix, int iy)
{
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLfloat fx = (GLfloat) ix;
const GLfloat fy = (GLfloat) iy;
const GLfloat coverage = compute_coveragef(line, ix, iy);
const GLuint i = line->span.end;
(void) swrast;
if (coverage == 0.0F)
return;
line->span.end++;
line->span.array->coverage[i] = coverage;
line->span.array->x[i] = ix;
line->span.array->y[i] = iy;
/*
* Compute Z, color, texture coords, fog for the fragment by
* solving the plane equations at (ix,iy).
*/
#ifdef DO_Z
line->span.array->z[i] = (GLuint) solve_plane(fx, fy, line->zPlane);
#endif
line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane);
line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane);
line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane);
line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane);
#if defined(DO_ATTRIBS)
ATTRIB_LOOP_BEGIN
GLfloat (*attribArray)[4] = line->span.array->attribs[attr];
if (attr >= VARYING_SLOT_TEX0 && attr < VARYING_SLOT_VAR0
&& !_swrast_use_fragment_program(ctx)) {
/* texcoord w/ divide by Q */
const GLuint unit = attr - VARYING_SLOT_TEX0;
const GLfloat invQ = solve_plane_recip(fx, fy, line->attrPlane[attr][3]);
GLuint c;
for (c = 0; c < 3; c++) {
attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invQ;
}
line->span.array->lambda[unit][i]
= compute_lambda(line->attrPlane[attr][0],
line->attrPlane[attr][1], invQ,
line->texWidth[attr], line->texHeight[attr]);
}
else {
/* non-texture attrib */
const GLfloat invW = solve_plane_recip(fx, fy, line->wPlane);
GLuint c;
for (c = 0; c < 4; c++) {
attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invW;
}
}
ATTRIB_LOOP_END
#endif
if (line->span.end == SWRAST_MAX_WIDTH) {
_swrast_write_rgba_span(ctx, &(line->span));
line->span.end = 0; /* reset counter */
}
}
/*
* Line setup
*/
static void
NAME(line)(struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLfloat tStart, tEnd; /* segment start, end along line length */
GLboolean inSegment;
GLint iLen, i;
/* Init the LineInfo struct */
struct LineInfo line;
line.x0 = v0->attrib[VARYING_SLOT_POS][0];
line.y0 = v0->attrib[VARYING_SLOT_POS][1];
line.x1 = v1->attrib[VARYING_SLOT_POS][0];
line.y1 = v1->attrib[VARYING_SLOT_POS][1];
line.dx = line.x1 - line.x0;
line.dy = line.y1 - line.y0;
line.len = sqrtf(line.dx * line.dx + line.dy * line.dy);
line.halfWidth = 0.5F * CLAMP(ctx->Line.Width,
ctx->Const.MinLineWidthAA,
ctx->Const.MaxLineWidthAA);
if (line.len == 0.0F || util_is_inf_or_nan(line.len))
return;
INIT_SPAN(line.span, GL_LINE);
line.span.arrayMask = SPAN_XY | SPAN_COVERAGE;
line.span.facing = swrast->PointLineFacing;
line.xAdj = line.dx / line.len * line.halfWidth;
line.yAdj = line.dy / line.len * line.halfWidth;
#ifdef DO_Z
line.span.arrayMask |= SPAN_Z;
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->attrib[VARYING_SLOT_POS][2], v1->attrib[VARYING_SLOT_POS][2], line.zPlane);
#endif
line.span.arrayMask |= SPAN_RGBA;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[RCOMP], v1->color[RCOMP], line.rPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[GCOMP], v1->color[GCOMP], line.gPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[BCOMP], v1->color[BCOMP], line.bPlane);
compute_plane(line.x0, line.y0, line.x1, line.y1,
v0->color[ACOMP], v1->color[ACOMP], line.aPlane);
}
else {
constant_plane(v1->color[RCOMP], line.rPlane);
constant_plane(v1->color[GCOMP], line.gPlane);
constant_plane(v1->color[BCOMP], line.bPlane);
constant_plane(v1->color[ACOMP], line.aPlane);
}
#if defined(DO_ATTRIBS)
{
const GLfloat invW0 = v0->attrib[VARYING_SLOT_POS][3];
const GLfloat invW1 = v1->attrib[VARYING_SLOT_POS][3];
line.span.arrayMask |= SPAN_LAMBDA;
compute_plane(line.x0, line.y0, line.x1, line.y1, invW0, invW1, line.wPlane);
ATTRIB_LOOP_BEGIN
GLuint c;
if (swrast->_InterpMode[attr] == GL_FLAT) {
for (c = 0; c < 4; c++) {
constant_plane(v1->attrib[attr][c], line.attrPlane[attr][c]);
}
}
else {
for (c = 0; c < 4; c++) {
const GLfloat a0 = v0->attrib[attr][c] * invW0;
const GLfloat a1 = v1->attrib[attr][c] * invW1;
compute_plane(line.x0, line.y0, line.x1, line.y1, a0, a1,
line.attrPlane[attr][c]);
}
}
line.span.arrayAttribs |= BITFIELD64_BIT(attr);
if (attr >= VARYING_SLOT_TEX0 && attr < VARYING_SLOT_VAR0) {
const GLuint u = attr - VARYING_SLOT_TEX0;
const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
if (obj) {
const struct gl_texture_image *texImage =
_mesa_base_tex_image(obj);
line.texWidth[attr] = (GLfloat) texImage->Width;
line.texHeight[attr] = (GLfloat) texImage->Height;
}
}
ATTRIB_LOOP_END
}
#endif
tStart = tEnd = 0.0;
inSegment = GL_FALSE;
iLen = (GLint) line.len;
if (ctx->Line.StippleFlag) {
for (i = 0; i < iLen; i++) {
const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
if ((1 << bit) & ctx->Line.StipplePattern) {
/* stipple bit is on */
const GLfloat t = (GLfloat) i / (GLfloat) line.len;
if (!inSegment) {
/* start new segment */
inSegment = GL_TRUE;
tStart = t;
}
else {
/* still in the segment, extend it */
tEnd = t;
}
}
else {
/* stipple bit is off */
if (inSegment && (tEnd > tStart)) {
/* draw the segment */
segment(ctx, &line, NAME(plot), tStart, tEnd);
inSegment = GL_FALSE;
}
else {
/* still between segments, do nothing */
}
}
swrast->StippleCounter++;
}
if (inSegment) {
/* draw the final segment of the line */
segment(ctx, &line, NAME(plot), tStart, 1.0F);
}
}
else {
/* non-stippled */
segment(ctx, &line, NAME(plot), 0.0, 1.0);
}
_swrast_write_rgba_span(ctx, &(line.span));
}
#undef DO_Z
#undef DO_ATTRIBS
#undef NAME

View File

@ -1,296 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Antialiased Triangle rasterizers
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "main/state.h"
#include "s_aatriangle.h"
#include "s_context.h"
#include "s_span.h"
/*
* Compute coefficients of a plane using the X,Y coords of the v0, v1, v2
* vertices and the given Z values.
* A point (x,y,z) lies on plane iff a*x+b*y+c*z+d = 0.
*/
static inline void
compute_plane(const GLfloat v0[], const GLfloat v1[], const GLfloat v2[],
GLfloat z0, GLfloat z1, GLfloat z2, GLfloat plane[4])
{
const GLfloat px = v1[0] - v0[0];
const GLfloat py = v1[1] - v0[1];
const GLfloat pz = z1 - z0;
const GLfloat qx = v2[0] - v0[0];
const GLfloat qy = v2[1] - v0[1];
const GLfloat qz = z2 - z0;
/* Crossproduct "(a,b,c):= dv1 x dv2" is orthogonal to plane. */
const GLfloat a = py * qz - pz * qy;
const GLfloat b = pz * qx - px * qz;
const GLfloat c = px * qy - py * qx;
/* Point on the plane = "r*(a,b,c) + w", with fixed "r" depending
on the distance of plane from origin and arbitrary "w" parallel
to the plane. */
/* The scalar product "(r*(a,b,c)+w)*(a,b,c)" is "r*(a^2+b^2+c^2)",
which is equal to "-d" below. */
const GLfloat d = -(a * v0[0] + b * v0[1] + c * z0);
plane[0] = a;
plane[1] = b;
plane[2] = c;
plane[3] = d;
}
/*
* Compute coefficients of a plane with a constant Z value.
*/
static inline void
constant_plane(GLfloat value, GLfloat plane[4])
{
plane[0] = 0.0;
plane[1] = 0.0;
plane[2] = -1.0;
plane[3] = value;
}
#define CONSTANT_PLANE(VALUE, PLANE) \
do { \
PLANE[0] = 0.0F; \
PLANE[1] = 0.0F; \
PLANE[2] = -1.0F; \
PLANE[3] = VALUE; \
} while (0)
/*
* Solve plane equation for Z at (X,Y).
*/
static inline GLfloat
solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
{
assert(plane[2] != 0.0F);
return (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
}
#define SOLVE_PLANE(X, Y, PLANE) \
((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2])
/*
* Solve plane and return clamped GLchan value.
*/
static inline GLchan
solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4])
{
const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
#if CHAN_TYPE == GL_FLOAT
return CLAMP(z, 0.0F, CHAN_MAXF);
#else
if (z < 0)
return 0;
else if (z > CHAN_MAX)
return CHAN_MAX;
return (GLchan) lroundf(z);
#endif
}
static inline GLfloat
plane_dx(const GLfloat plane[4])
{
return -plane[0] / plane[2];
}
static inline GLfloat
plane_dy(const GLfloat plane[4])
{
return -plane[1] / plane[2];
}
/*
* Compute how much (area) of the given pixel is inside the triangle.
* Vertices MUST be specified in counter-clockwise order.
* Return: coverage in [0, 1].
*/
static GLfloat
compute_coveragef(const GLfloat v0[3], const GLfloat v1[3],
const GLfloat v2[3], GLint winx, GLint winy)
{
/* Given a position [0,3]x[0,3] return the sub-pixel sample position.
* Contributed by Ray Tice.
*
* Jitter sample positions -
* - average should be .5 in x & y for each column
* - each of the 16 rows and columns should be used once
* - the rectangle formed by the first four points
* should contain the other points
* - the distrubition should be fairly even in any given direction
*
* The pattern drawn below isn't optimal, but it's better than a regular
* grid. In the drawing, the center of each subpixel is surrounded by
* four dots. The "x" marks the jittered position relative to the
* subpixel center.
*/
#define POS(a, b) (0.5+a*4+b)/16
static const GLfloat samples[16][2] = {
/* start with the four corners */
{ POS(0, 2), POS(0, 0) },
{ POS(3, 3), POS(0, 2) },
{ POS(0, 0), POS(3, 1) },
{ POS(3, 1), POS(3, 3) },
/* continue with interior samples */
{ POS(1, 1), POS(0, 1) },
{ POS(2, 0), POS(0, 3) },
{ POS(0, 3), POS(1, 3) },
{ POS(1, 2), POS(1, 0) },
{ POS(2, 3), POS(1, 2) },
{ POS(3, 2), POS(1, 1) },
{ POS(0, 1), POS(2, 2) },
{ POS(1, 0), POS(2, 1) },
{ POS(2, 1), POS(2, 3) },
{ POS(3, 0), POS(2, 0) },
{ POS(1, 3), POS(3, 0) },
{ POS(2, 2), POS(3, 2) }
};
const GLfloat x = (GLfloat) winx;
const GLfloat y = (GLfloat) winy;
const GLfloat dx0 = v1[0] - v0[0];
const GLfloat dy0 = v1[1] - v0[1];
const GLfloat dx1 = v2[0] - v1[0];
const GLfloat dy1 = v2[1] - v1[1];
const GLfloat dx2 = v0[0] - v2[0];
const GLfloat dy2 = v0[1] - v2[1];
GLint stop = 4, i;
GLfloat insideCount = 16.0F;
assert(dx0 * dy1 - dx1 * dy0 >= 0.0); /* area >= 0.0 */
for (i = 0; i < stop; i++) {
const GLfloat sx = x + samples[i][0];
const GLfloat sy = y + samples[i][1];
/* cross product determines if sample is inside or outside each edge */
GLfloat cross = (dx0 * (sy - v0[1]) - dy0 * (sx - v0[0]));
/* Check if the sample is exactly on an edge. If so, let cross be a
* positive or negative value depending on the direction of the edge.
*/
if (cross == 0.0F)
cross = dx0 + dy0;
if (cross < 0.0F) {
/* sample point is outside first edge */
insideCount -= 1.0F;
stop = 16;
}
else {
/* sample point is inside first edge */
cross = (dx1 * (sy - v1[1]) - dy1 * (sx - v1[0]));
if (cross == 0.0F)
cross = dx1 + dy1;
if (cross < 0.0F) {
/* sample point is outside second edge */
insideCount -= 1.0F;
stop = 16;
}
else {
/* sample point is inside first and second edges */
cross = (dx2 * (sy - v2[1]) - dy2 * (sx - v2[0]));
if (cross == 0.0F)
cross = dx2 + dy2;
if (cross < 0.0F) {
/* sample point is outside third edge */
insideCount -= 1.0F;
stop = 16;
}
}
}
}
if (stop == 4)
return 1.0F;
else
return insideCount * (1.0F / 16.0F);
}
static void
rgba_aa_tri(struct gl_context *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#include "s_aatritemp.h"
}
static void
general_aa_tri(struct gl_context *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
#define DO_Z
#define DO_ATTRIBS
#include "s_aatritemp.h"
}
/*
* Examine GL state and set swrast->Triangle to an
* appropriate antialiased triangle rasterizer function.
*/
void
_swrast_set_aa_triangle_function(struct gl_context *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
assert(ctx->Polygon.SmoothFlag);
if (ctx->Texture._EnabledCoordUnits != 0
|| _swrast_use_fragment_program(ctx)
|| swrast->_FogEnabled
|| _mesa_need_secondary_color(ctx)) {
SWRAST_CONTEXT(ctx)->Triangle = general_aa_tri;
}
else {
SWRAST_CONTEXT(ctx)->Triangle = rgba_aa_tri;
}
assert(SWRAST_CONTEXT(ctx)->Triangle);
}

View File

@ -1,38 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_AATRIANGLE_H
#define S_AATRIANGLE_H
struct gl_context;
extern void
_swrast_set_aa_triangle_function(struct gl_context *ctx);
#endif

View File

@ -1,343 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Antialiased Triangle Rasterizer Template
*
* This file is #include'd to generate custom AA triangle rasterizers.
* NOTE: this code hasn't been optimized yet. That'll come after it
* works correctly.
*
* The following macros may be defined to indicate what auxillary information
* must be copmuted across the triangle:
* DO_Z - if defined, compute Z values
* DO_ATTRIBS - if defined, compute texcoords, varying, etc.
*/
/*void triangle( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
{
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLfloat *p0 = v0->attrib[VARYING_SLOT_POS];
const GLfloat *p1 = v1->attrib[VARYING_SLOT_POS];
const GLfloat *p2 = v2->attrib[VARYING_SLOT_POS];
const SWvertex *vMin, *vMid, *vMax;
GLint iyMin, iyMax;
GLfloat yMin, yMax;
GLboolean ltor;
GLfloat majDx, majDy; /* major (i.e. long) edge dx and dy */
SWspan span;
#ifdef DO_Z
GLfloat zPlane[4];
#endif
GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
#if defined(DO_ATTRIBS)
GLfloat attrPlane[VARYING_SLOT_MAX][4][4];
GLfloat wPlane[4]; /* win[3] */
#endif
GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceCullSign;
(void) swrast;
INIT_SPAN(span, GL_POLYGON);
span.arrayMask = SPAN_COVERAGE;
/* determine bottom to top order of vertices */
{
GLfloat y0 = v0->attrib[VARYING_SLOT_POS][1];
GLfloat y1 = v1->attrib[VARYING_SLOT_POS][1];
GLfloat y2 = v2->attrib[VARYING_SLOT_POS][1];
if (y0 <= y1) {
if (y1 <= y2) {
vMin = v0; vMid = v1; vMax = v2; /* y0<=y1<=y2 */
}
else if (y2 <= y0) {
vMin = v2; vMid = v0; vMax = v1; /* y2<=y0<=y1 */
}
else {
vMin = v0; vMid = v2; vMax = v1; bf = -bf; /* y0<=y2<=y1 */
}
}
else {
if (y0 <= y2) {
vMin = v1; vMid = v0; vMax = v2; bf = -bf; /* y1<=y0<=y2 */
}
else if (y2 <= y1) {
vMin = v2; vMid = v1; vMax = v0; bf = -bf; /* y2<=y1<=y0 */
}
else {
vMin = v1; vMid = v2; vMax = v0; /* y1<=y2<=y0 */
}
}
}
majDx = vMax->attrib[VARYING_SLOT_POS][0] - vMin->attrib[VARYING_SLOT_POS][0];
majDy = vMax->attrib[VARYING_SLOT_POS][1] - vMin->attrib[VARYING_SLOT_POS][1];
/* front/back-face determination and cullling */
{
const GLfloat botDx = vMid->attrib[VARYING_SLOT_POS][0] - vMin->attrib[VARYING_SLOT_POS][0];
const GLfloat botDy = vMid->attrib[VARYING_SLOT_POS][1] - vMin->attrib[VARYING_SLOT_POS][1];
const GLfloat area = majDx * botDy - botDx * majDy;
/* Do backface culling */
if (area * bf < 0 || area == 0 || util_is_inf_or_nan(area))
return;
ltor = (GLboolean) (area < 0.0F);
span.facing = area * swrast->_BackfaceSign > 0.0F;
}
/* Plane equation setup:
* We evaluate plane equations at window (x,y) coordinates in order
* to compute color, Z, fog, texcoords, etc. This isn't terribly
* efficient but it's easy and reliable.
*/
#ifdef DO_Z
compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane);
span.arrayMask |= SPAN_Z;
#endif
if (ctx->Light.ShadeModel == GL_SMOOTH) {
compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane);
compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane);
compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane);
compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane);
}
else {
constant_plane(v2->color[RCOMP], rPlane);
constant_plane(v2->color[GCOMP], gPlane);
constant_plane(v2->color[BCOMP], bPlane);
constant_plane(v2->color[ACOMP], aPlane);
}
span.arrayMask |= SPAN_RGBA;
#if defined(DO_ATTRIBS)
{
const GLfloat invW0 = v0->attrib[VARYING_SLOT_POS][3];
const GLfloat invW1 = v1->attrib[VARYING_SLOT_POS][3];
const GLfloat invW2 = v2->attrib[VARYING_SLOT_POS][3];
compute_plane(p0, p1, p2, invW0, invW1, invW2, wPlane);
span.attrStepX[VARYING_SLOT_POS][3] = plane_dx(wPlane);
span.attrStepY[VARYING_SLOT_POS][3] = plane_dy(wPlane);
ATTRIB_LOOP_BEGIN
GLuint c;
if (swrast->_InterpMode[attr] == GL_FLAT) {
for (c = 0; c < 4; c++) {
constant_plane(v2->attrib[attr][c] * invW2, attrPlane[attr][c]);
}
}
else {
for (c = 0; c < 4; c++) {
const GLfloat a0 = v0->attrib[attr][c] * invW0;
const GLfloat a1 = v1->attrib[attr][c] * invW1;
const GLfloat a2 = v2->attrib[attr][c] * invW2;
compute_plane(p0, p1, p2, a0, a1, a2, attrPlane[attr][c]);
}
}
for (c = 0; c < 4; c++) {
span.attrStepX[attr][c] = plane_dx(attrPlane[attr][c]);
span.attrStepY[attr][c] = plane_dy(attrPlane[attr][c]);
}
ATTRIB_LOOP_END
}
#endif
/* Begin bottom-to-top scan over the triangle.
* The long edge will either be on the left or right side of the
* triangle. We always scan from the long edge toward the shorter
* edges, stopping when we find that coverage = 0. If the long edge
* is on the left we scan left-to-right. Else, we scan right-to-left.
*/
yMin = vMin->attrib[VARYING_SLOT_POS][1];
yMax = vMax->attrib[VARYING_SLOT_POS][1];
iyMin = (GLint) yMin;
iyMax = (GLint) yMax + 1;
if (ltor) {
/* scan left to right */
const GLfloat *pMin = vMin->attrib[VARYING_SLOT_POS];
const GLfloat *pMid = vMid->attrib[VARYING_SLOT_POS];
const GLfloat *pMax = vMax->attrib[VARYING_SLOT_POS];
const GLfloat dxdy = majDx / majDy;
const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F;
GLint iy;
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic) private(iy) firstprivate(span)
#endif
for (iy = iyMin; iy < iyMax; iy++) {
GLfloat x = pMin[0] - (yMin - iy) * dxdy;
GLint ix, startX = (GLint) (x - xAdj);
GLuint count;
GLfloat coverage = 0.0F;
#ifdef _OPENMP
/* each thread needs to use a different (global) SpanArrays variable */
span.array = SWRAST_CONTEXT(ctx)->SpanArrays + omp_get_thread_num();
#endif
/* skip over fragments with zero coverage */
while (startX < SWRAST_MAX_WIDTH) {
coverage = compute_coveragef(pMin, pMid, pMax, startX, iy);
if (coverage > 0.0F)
break;
startX++;
}
/* enter interior of triangle */
ix = startX;
#if defined(DO_ATTRIBS)
/* compute attributes at left-most fragment */
span.attrStart[VARYING_SLOT_POS][3] = solve_plane(ix + 0.5F, iy + 0.5F, wPlane);
ATTRIB_LOOP_BEGIN
GLuint c;
for (c = 0; c < 4; c++) {
span.attrStart[attr][c] = solve_plane(ix + 0.5F, iy + 0.5F, attrPlane[attr][c]);
}
ATTRIB_LOOP_END
#endif
count = 0;
while (coverage > 0.0F) {
/* (cx,cy) = center of fragment */
const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
SWspanarrays *array = span.array;
array->coverage[count] = coverage;
#ifdef DO_Z
array->z[count] = (GLuint) solve_plane(cx, cy, zPlane);
#endif
array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane);
array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane);
array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane);
array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane);
ix++;
count++;
coverage = compute_coveragef(pMin, pMid, pMax, ix, iy);
}
if (ix > startX) {
span.x = startX;
span.y = iy;
span.end = (GLuint) ix - (GLuint) startX;
_swrast_write_rgba_span(ctx, &span);
}
}
}
else {
/* scan right to left */
const GLfloat *pMin = vMin->attrib[VARYING_SLOT_POS];
const GLfloat *pMid = vMid->attrib[VARYING_SLOT_POS];
const GLfloat *pMax = vMax->attrib[VARYING_SLOT_POS];
const GLfloat dxdy = majDx / majDy;
const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F;
GLint iy;
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic) private(iy) firstprivate(span)
#endif
for (iy = iyMin; iy < iyMax; iy++) {
GLfloat x = pMin[0] - (yMin - iy) * dxdy;
GLint ix, left, startX = (GLint) (x + xAdj);
GLuint count, n;
GLfloat coverage = 0.0F;
#ifdef _OPENMP
/* each thread needs to use a different (global) SpanArrays variable */
span.array = SWRAST_CONTEXT(ctx)->SpanArrays + omp_get_thread_num();
#endif
/* make sure we're not past the window edge */
if (startX >= ctx->DrawBuffer->_Xmax) {
startX = ctx->DrawBuffer->_Xmax - 1;
}
/* skip fragments with zero coverage */
while (startX > 0) {
coverage = compute_coveragef(pMin, pMax, pMid, startX, iy);
if (coverage > 0.0F)
break;
startX--;
}
/* enter interior of triangle */
ix = startX;
count = 0;
while (coverage > 0.0F) {
/* (cx,cy) = center of fragment */
const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
SWspanarrays *array = span.array;
assert(ix >= 0);
array->coverage[ix] = coverage;
#ifdef DO_Z
array->z[ix] = (GLuint) solve_plane(cx, cy, zPlane);
#endif
array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane);
array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane);
array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane);
array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane);
ix--;
count++;
coverage = compute_coveragef(pMin, pMax, pMid, ix, iy);
}
#if defined(DO_ATTRIBS)
/* compute attributes at left-most fragment */
span.attrStart[VARYING_SLOT_POS][3] = solve_plane(ix + 1.5F, iy + 0.5F, wPlane);
ATTRIB_LOOP_BEGIN
GLuint c;
for (c = 0; c < 4; c++) {
span.attrStart[attr][c] = solve_plane(ix + 1.5F, iy + 0.5F, attrPlane[attr][c]);
}
ATTRIB_LOOP_END
#endif
if (startX > ix) {
n = (GLuint) startX - (GLuint) ix;
left = ix + 1;
/* shift all values to the left */
/* XXX this is temporary */
{
SWspanarrays *array = span.array;
GLint j;
for (j = 0; j < (GLint) n; j++) {
array->coverage[j] = array->coverage[j + left];
COPY_CHAN4(array->rgba[j], array->rgba[j + left]);
#ifdef DO_Z
array->z[j] = array->z[j + left];
#endif
}
}
span.x = left;
span.y = iy;
span.end = n;
_swrast_write_rgba_span(ctx, &span);
}
}
}
}
#undef DO_Z
#undef DO_ATTRIBS
#undef DO_OCCLUSION_TEST

View File

@ -1,159 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file swrast/s_alpha.c
* \brief Functions to apply alpha test.
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "s_alpha.h"
#include "s_context.h"
#define ALPHA_TEST(ALPHA, LOOP_CODE) \
do { \
switch (ctx->Color.AlphaFunc) { \
case GL_LESS: \
for (i = 0; i < n; i++) { \
mask[i] &= (ALPHA < ref); \
LOOP_CODE; \
} \
break; \
case GL_LEQUAL: \
for (i = 0; i < n; i++) { \
mask[i] &= (ALPHA <= ref); \
LOOP_CODE; \
} \
break; \
case GL_GEQUAL: \
for (i = 0; i < n; i++) { \
mask[i] &= (ALPHA >= ref); \
LOOP_CODE; \
} \
break; \
case GL_GREATER: \
for (i = 0; i < n; i++) { \
mask[i] &= (ALPHA > ref); \
LOOP_CODE; \
} \
break; \
case GL_NOTEQUAL: \
for (i = 0; i < n; i++) { \
mask[i] &= (ALPHA != ref); \
LOOP_CODE; \
} \
break; \
case GL_EQUAL: \
for (i = 0; i < n; i++) { \
mask[i] &= (ALPHA == ref); \
LOOP_CODE; \
} \
break; \
default: \
_mesa_problem(ctx, "Invalid alpha test in _swrast_alpha_test" ); \
return 0; \
} \
} while (0)
/**
* Perform the alpha test for an array of pixels.
* For pixels that fail the test, mask[i] will be set to 0.
* \return 0 if all pixels in the span failed the alpha test,
* 1 if one or more pixels passed the alpha test.
*/
GLint
_swrast_alpha_test(const struct gl_context *ctx, SWspan *span)
{
const GLuint n = span->end;
GLubyte *mask = span->array->mask;
GLuint i;
if (ctx->Color.AlphaFunc == GL_ALWAYS) {
/* do nothing */
return 1;
}
else if (ctx->Color.AlphaFunc == GL_NEVER) {
/* All pixels failed - caller should check for this return value and
* act accordingly.
*/
span->writeAll = GL_FALSE;
return 0;
}
if (span->arrayMask & SPAN_RGBA) {
/* Use array's alpha values */
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
GLubyte (*rgba)[4] = span->array->rgba8;
GLubyte ref;
CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
ALPHA_TEST(rgba[i][ACOMP], ;);
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
GLushort (*rgba)[4] = span->array->rgba16;
GLushort ref;
CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
ALPHA_TEST(rgba[i][ACOMP], ;);
}
else {
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
const GLfloat ref = ctx->Color.AlphaRef;
ALPHA_TEST(rgba[i][ACOMP], ;);
}
}
else {
/* Interpolate alpha values */
assert(span->interpMask & SPAN_RGBA);
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
const GLfixed alphaStep = span->alphaStep;
GLfixed alpha = span->alpha;
GLubyte ref;
CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
const GLfixed alphaStep = span->alphaStep;
GLfixed alpha = span->alpha;
GLushort ref;
CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
}
else {
const GLfloat alphaStep = FixedToFloat(span->alphaStep);
GLfloat alpha = FixedToFloat(span->alpha);
const GLfloat ref = ctx->Color.AlphaRef;
ALPHA_TEST(alpha, alpha += alphaStep);
}
}
span->writeAll = GL_FALSE;
/* XXX examine mask[] values? */
return 1;
}

View File

@ -1,39 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_ALPHA_H
#define S_ALPHA_H
#include "main/glheader.h"
#include "s_span.h"
struct gl_context;
extern GLint
_swrast_alpha_test( const struct gl_context *ctx, SWspan *span );
#endif

View File

@ -1,592 +0,0 @@
/*
* Copyright (C) 2004 David Airlie All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/macros.h"
#include "main/atifragshader.h"
#include "main/samplerobj.h"
#include "swrast/s_atifragshader.h"
#include "swrast/s_context.h"
#define ATI_FS_INPUT_PRIMARY 0
#define ATI_FS_INPUT_SECONDARY 1
/**
* State for executing ATI fragment shader.
*/
struct atifs_machine
{
GLfloat Registers[6][4]; /** six temporary registers */
GLfloat PrevPassRegisters[6][4];
GLfloat Inputs[2][4]; /** Primary, secondary input colors */
};
/**
* Fetch a texel.
*/
static void
fetch_texel(struct gl_context * ctx, const GLfloat texcoord[4], GLfloat lambda,
GLuint unit, GLfloat color[4])
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* XXX use a float-valued TextureSample routine here!!! */
swrast->TextureSample[unit](ctx, _mesa_get_samplerobj(ctx, unit),
ctx->Texture.Unit[unit]._Current,
1, (const GLfloat(*)[4]) texcoord,
&lambda, (GLfloat (*)[4]) color);
}
static void
apply_swizzle(GLfloat values[4], GLuint swizzle)
{
GLfloat s, t, r, q;
s = values[0];
t = values[1];
r = values[2];
q = values[3];
switch (swizzle) {
case GL_SWIZZLE_STR_ATI:
values[0] = s;
values[1] = t;
values[2] = r;
break;
case GL_SWIZZLE_STQ_ATI:
values[0] = s;
values[1] = t;
values[2] = q;
break;
case GL_SWIZZLE_STR_DR_ATI:
values[0] = s / r;
values[1] = t / r;
values[2] = 1 / r;
break;
case GL_SWIZZLE_STQ_DQ_ATI:
/* make sure q is not 0 to avoid problems later with infinite values (texture lookup)? */
if (q == 0.0F)
q = 0.000000001F;
values[0] = s / q;
values[1] = t / q;
values[2] = 1.0F / q;
break;
}
values[3] = 0.0;
}
static void
apply_src_rep(GLint optype, GLuint rep, GLfloat * val)
{
GLint i;
GLint start, end;
if (!rep)
return;
start = optype ? 3 : 0;
end = 4;
for (i = start; i < end; i++) {
switch (rep) {
case GL_RED:
val[i] = val[0];
break;
case GL_GREEN:
val[i] = val[1];
break;
case GL_BLUE:
val[i] = val[2];
break;
case GL_ALPHA:
val[i] = val[3];
break;
}
}
}
static void
apply_src_mod(GLint optype, GLuint mod, GLfloat * val)
{
GLint i;
GLint start, end;
if (!mod)
return;
start = optype ? 3 : 0;
end = 4;
for (i = start; i < end; i++) {
if (mod & GL_COMP_BIT_ATI)
val[i] = 1 - val[i];
if (mod & GL_BIAS_BIT_ATI)
val[i] = val[i] - 0.5F;
if (mod & GL_2X_BIT_ATI)
val[i] = 2 * val[i];
if (mod & GL_NEGATE_BIT_ATI)
val[i] = -val[i];
}
}
static void
apply_dst_mod(GLuint optype, GLuint mod, GLfloat * val)
{
GLint i;
GLint has_sat = mod & GL_SATURATE_BIT_ATI;
GLint start, end;
mod &= ~GL_SATURATE_BIT_ATI;
start = optype ? 3 : 0;
end = optype ? 4 : 3;
for (i = start; i < end; i++) {
switch (mod) {
case GL_2X_BIT_ATI:
val[i] = 2 * val[i];
break;
case GL_4X_BIT_ATI:
val[i] = 4 * val[i];
break;
case GL_8X_BIT_ATI:
val[i] = 8 * val[i];
break;
case GL_HALF_BIT_ATI:
val[i] = val[i] * 0.5F;
break;
case GL_QUARTER_BIT_ATI:
val[i] = val[i] * 0.25F;
break;
case GL_EIGHTH_BIT_ATI:
val[i] = val[i] * 0.125F;
break;
}
if (has_sat) {
if (val[i] < 0.0F)
val[i] = 0.0F;
else if (val[i] > 1.0F)
val[i] = 1.0F;
}
else {
if (val[i] < -8.0F)
val[i] = -8.0F;
else if (val[i] > 8.0F)
val[i] = 8.0F;
}
}
}
static void
write_dst_addr(GLuint optype, GLuint mod, GLuint mask, GLfloat * src,
GLfloat * dst)
{
GLint i;
apply_dst_mod(optype, mod, src);
if (optype == ATI_FRAGMENT_SHADER_COLOR_OP) {
if (mask) {
if (mask & GL_RED_BIT_ATI)
dst[0] = src[0];
if (mask & GL_GREEN_BIT_ATI)
dst[1] = src[1];
if (mask & GL_BLUE_BIT_ATI)
dst[2] = src[2];
}
else {
for (i = 0; i < 3; i++)
dst[i] = src[i];
}
}
else
dst[3] = src[3];
}
static void
finish_pass(struct atifs_machine *machine)
{
GLint i;
for (i = 0; i < 6; i++) {
COPY_4V(machine->PrevPassRegisters[i], machine->Registers[i]);
}
}
static void
handle_pass_op(struct atifs_machine *machine, struct atifs_setupinst *texinst,
const SWspan *span, GLuint column, GLuint idx)
{
GLuint swizzle = texinst->swizzle;
GLuint pass_tex = texinst->src;
if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) {
pass_tex -= GL_TEXTURE0_ARB;
COPY_4V(machine->Registers[idx],
span->array->attribs[VARYING_SLOT_TEX0 + pass_tex][column]);
}
else if (pass_tex >= GL_REG_0_ATI && pass_tex <= GL_REG_5_ATI) {
pass_tex -= GL_REG_0_ATI;
COPY_4V(machine->Registers[idx], machine->PrevPassRegisters[pass_tex]);
}
apply_swizzle(machine->Registers[idx], swizzle);
}
static void
handle_sample_op(struct gl_context * ctx, struct atifs_machine *machine,
struct atifs_setupinst *texinst, const SWspan *span,
GLuint column, GLuint idx)
{
/* sample from unit idx using texinst->src as coords */
GLuint swizzle = texinst->swizzle;
GLuint coord_source = texinst->src;
GLfloat tex_coords[4] = { 0 };
if (coord_source >= GL_TEXTURE0_ARB && coord_source <= GL_TEXTURE7_ARB) {
coord_source -= GL_TEXTURE0_ARB;
COPY_4V(tex_coords,
span->array->attribs[VARYING_SLOT_TEX0 + coord_source][column]);
}
else if (coord_source >= GL_REG_0_ATI && coord_source <= GL_REG_5_ATI) {
coord_source -= GL_REG_0_ATI;
COPY_4V(tex_coords, machine->PrevPassRegisters[coord_source]);
}
apply_swizzle(tex_coords, swizzle);
fetch_texel(ctx, tex_coords, 0.0F, idx, machine->Registers[idx]);
}
#define SETUP_SRC_REG(optype, i, x) \
do { \
COPY_4V(src[optype][i], x); \
} while (0)
/**
* Execute the given fragment shader.
* NOTE: we do everything in single-precision floating point
* \param ctx - rendering context
* \param shader - the shader to execute
* \param machine - virtual machine state
* \param span - the SWspan we're operating on
* \param column - which pixel [i] we're operating on in the span
*/
static void
execute_shader(struct gl_context *ctx, const struct ati_fragment_shader *shader,
struct atifs_machine *machine, const SWspan *span,
GLuint column)
{
GLuint pc;
struct atifs_instruction *inst;
struct atifs_setupinst *texinst;
GLint optype;
GLuint i;
GLint j, pass;
GLint dstreg;
GLfloat src[2][3][4];
GLfloat zeros[4] = { 0.0, 0.0, 0.0, 0.0 };
GLfloat ones[4] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat dst[2][4], *dstp;
for (pass = 0; pass < shader->NumPasses; pass++) {
if (pass > 0)
finish_pass(machine);
for (j = 0; j < MAX_NUM_FRAGMENT_REGISTERS_ATI; j++) {
texinst = &shader->SetupInst[pass][j];
if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP)
handle_pass_op(machine, texinst, span, column, j);
else if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP)
handle_sample_op(ctx, machine, texinst, span, column, j);
}
for (pc = 0; pc < shader->numArithInstr[pass]; pc++) {
inst = &shader->Instructions[pass][pc];
/* setup the source registers for color and alpha ops */
for (optype = 0; optype < 2; optype++) {
for (i = 0; i < inst->ArgCount[optype]; i++) {
GLint index = inst->SrcReg[optype][i].Index;
if (index >= GL_REG_0_ATI && index <= GL_REG_5_ATI)
SETUP_SRC_REG(optype, i,
machine->Registers[index - GL_REG_0_ATI]);
else if (index >= GL_CON_0_ATI && index <= GL_CON_7_ATI) {
if (shader->LocalConstDef & (1 << (index - GL_CON_0_ATI))) {
SETUP_SRC_REG(optype, i,
shader->Constants[index - GL_CON_0_ATI]);
} else {
SETUP_SRC_REG(optype, i,
ctx->ATIFragmentShader.GlobalConstants[index - GL_CON_0_ATI]);
}
}
else if (index == GL_ONE)
SETUP_SRC_REG(optype, i, ones);
else if (index == GL_ZERO)
SETUP_SRC_REG(optype, i, zeros);
else if (index == GL_PRIMARY_COLOR_EXT)
SETUP_SRC_REG(optype, i,
machine->Inputs[ATI_FS_INPUT_PRIMARY]);
else if (index == GL_SECONDARY_INTERPOLATOR_ATI)
SETUP_SRC_REG(optype, i,
machine->Inputs[ATI_FS_INPUT_SECONDARY]);
apply_src_rep(optype, inst->SrcReg[optype][i].argRep,
src[optype][i]);
apply_src_mod(optype, inst->SrcReg[optype][i].argMod,
src[optype][i]);
}
}
/* Execute the operations - color then alpha */
for (optype = 0; optype < 2; optype++) {
if (inst->Opcode[optype]) {
switch (inst->Opcode[optype]) {
case GL_ADD_ATI:
if (!optype)
for (i = 0; i < 3; i++) {
dst[optype][i] =
src[optype][0][i] + src[optype][1][i];
}
else
dst[optype][3] = src[optype][0][3] + src[optype][1][3];
break;
case GL_SUB_ATI:
if (!optype)
for (i = 0; i < 3; i++) {
dst[optype][i] =
src[optype][0][i] - src[optype][1][i];
}
else
dst[optype][3] = src[optype][0][3] - src[optype][1][3];
break;
case GL_MUL_ATI:
if (!optype)
for (i = 0; i < 3; i++) {
dst[optype][i] =
src[optype][0][i] * src[optype][1][i];
}
else
dst[optype][3] = src[optype][0][3] * src[optype][1][3];
break;
case GL_MAD_ATI:
if (!optype)
for (i = 0; i < 3; i++) {
dst[optype][i] =
src[optype][0][i] * src[optype][1][i] +
src[optype][2][i];
}
else
dst[optype][3] =
src[optype][0][3] * src[optype][1][3] +
src[optype][2][3];
break;
case GL_LERP_ATI:
if (!optype)
for (i = 0; i < 3; i++) {
dst[optype][i] =
src[optype][0][i] * src[optype][1][i] + (1 -
src
[optype]
[0][i]) *
src[optype][2][i];
}
else
dst[optype][3] =
src[optype][0][3] * src[optype][1][3] + (1 -
src[optype]
[0][3]) *
src[optype][2][3];
break;
case GL_MOV_ATI:
if (!optype)
for (i = 0; i < 3; i++) {
dst[optype][i] = src[optype][0][i];
}
else
dst[optype][3] = src[optype][0][3];
break;
case GL_CND_ATI:
if (!optype) {
for (i = 0; i < 3; i++) {
dst[optype][i] =
(src[optype][2][i] >
0.5F) ? src[optype][0][i] : src[optype][1][i];
}
}
else {
dst[optype][3] =
(src[optype][2][3] >
0.5F) ? src[optype][0][3] : src[optype][1][3];
}
break;
case GL_CND0_ATI:
if (!optype)
for (i = 0; i < 3; i++) {
dst[optype][i] =
(src[optype][2][i] >=
0) ? src[optype][0][i] : src[optype][1][i];
}
else {
dst[optype][3] =
(src[optype][2][3] >=
0) ? src[optype][0][3] : src[optype][1][3];
}
break;
case GL_DOT2_ADD_ATI:
{
GLfloat result;
/* DOT 2 always uses the source from the color op */
/* could save recalculation of dot products for alpha inst */
result = src[0][0][0] * src[0][1][0] +
src[0][0][1] * src[0][1][1] + src[0][2][2];
if (!optype) {
for (i = 0; i < 3; i++) {
dst[optype][i] = result;
}
}
else
dst[optype][3] = result;
}
break;
case GL_DOT3_ATI:
{
GLfloat result;
/* DOT 3 always uses the source from the color op */
result = src[0][0][0] * src[0][1][0] +
src[0][0][1] * src[0][1][1] +
src[0][0][2] * src[0][1][2];
if (!optype) {
for (i = 0; i < 3; i++) {
dst[optype][i] = result;
}
}
else
dst[optype][3] = result;
}
break;
case GL_DOT4_ATI:
{
GLfloat result;
/* DOT 4 always uses the source from the color op */
result = src[0][0][0] * src[0][1][0] +
src[0][0][1] * src[0][1][1] +
src[0][0][2] * src[0][1][2] +
src[0][0][3] * src[0][1][3];
if (!optype) {
for (i = 0; i < 3; i++) {
dst[optype][i] = result;
}
}
else
dst[optype][3] = result;
}
break;
}
}
}
/* write out the destination registers */
for (optype = 0; optype < 2; optype++) {
if (inst->Opcode[optype]) {
dstreg = inst->DstReg[optype].Index;
dstp = machine->Registers[dstreg - GL_REG_0_ATI];
if ((optype == 0) || ((inst->Opcode[1] != GL_DOT2_ADD_ATI) &&
(inst->Opcode[1] != GL_DOT3_ATI) && (inst->Opcode[1] != GL_DOT4_ATI)))
write_dst_addr(optype, inst->DstReg[optype].dstMod,
inst->DstReg[optype].dstMask, dst[optype],
dstp);
else
write_dst_addr(1, inst->DstReg[0].dstMod, 0, dst[1], dstp);
}
}
}
}
}
/**
* Init fragment shader virtual machine state.
*/
static void
init_machine(struct gl_context * ctx, struct atifs_machine *machine,
const struct ati_fragment_shader *shader,
const SWspan *span, GLuint col)
{
GLfloat (*inputs)[4] = machine->Inputs;
GLint i, j;
for (i = 0; i < 6; i++) {
for (j = 0; j < 4; j++)
machine->Registers[i][j] = 0.0;
}
COPY_4V(inputs[ATI_FS_INPUT_PRIMARY], span->array->attribs[VARYING_SLOT_COL0][col]);
COPY_4V(inputs[ATI_FS_INPUT_SECONDARY], span->array->attribs[VARYING_SLOT_COL1][col]);
}
/**
* Execute the current ATI shader program, operating on the given span.
*/
void
_swrast_exec_fragment_shader(struct gl_context * ctx, SWspan *span)
{
const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
struct atifs_machine machine;
GLuint i;
/* incoming colors should be floats */
assert(span->array->ChanType == GL_FLOAT);
for (i = 0; i < span->end; i++) {
if (span->array->mask[i]) {
init_machine(ctx, &machine, shader, span, i);
execute_shader(ctx, shader, &machine, span, i);
/* store result color */
{
const GLfloat *colOut = machine.Registers[0];
/*fprintf(stderr,"outputs %f %f %f %f\n",
colOut[0], colOut[1], colOut[2], colOut[3]); */
COPY_4V(span->array->attribs[VARYING_SLOT_COL0][i], colOut);
}
}
}
}

View File

@ -1,37 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2003 David Airlie All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_ATIFRAGSHADER_H
#define S_ATIFRAGSHADER_H
#include "s_span.h"
struct gl_context;
extern void
_swrast_exec_fragment_shader( struct gl_context *ctx, SWspan *span );
#endif

View File

@ -1,223 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file swrast/s_bitmap.c
* \brief glBitmap rendering.
* \author Brian Paul
*/
#include "main/glheader.h"
#include "main/bufferobj.h"
#include "main/condrender.h"
#include "main/image.h"
#include "main/macros.h"
#include "main/pbo.h"
#include "s_context.h"
#include "s_span.h"
/**
* Render a bitmap.
* Called via ctx->Driver.Bitmap()
* All parameter error checking will have been done before this is called.
*/
void
_swrast_Bitmap( struct gl_context *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
{
GLint row, col;
GLuint count = 0;
SWspan span;
assert(ctx->RenderMode == GL_RENDER);
if (!_mesa_check_conditional_render(ctx))
return; /* don't draw */
bitmap = (const GLubyte *) _mesa_map_pbo_source(ctx, unpack, bitmap);
if (!bitmap)
return;
swrast_render_start(ctx);
if (SWRAST_CONTEXT(ctx)->NewState)
_swrast_validate_derived( ctx );
INIT_SPAN(span, GL_BITMAP);
span.end = width;
span.arrayMask = SPAN_XY;
_swrast_span_default_attribs(ctx, &span);
for (row = 0; row < height; row++) {
const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
if (unpack->LsbFirst) {
/* Lsb first */
GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
for (col = 0; col < width; col++) {
if (*src & mask) {
span.array->x[count] = px + col;
span.array->y[count] = py + row;
count++;
}
if (mask == 128U) {
src++;
mask = 1U;
}
else {
mask = mask << 1;
}
}
/* get ready for next row */
if (mask != 1)
src++;
}
else {
/* Msb first */
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (col = 0; col < width; col++) {
if (*src & mask) {
span.array->x[count] = px + col;
span.array->y[count] = py + row;
count++;
}
if (mask == 1U) {
src++;
mask = 128U;
}
else {
mask = mask >> 1;
}
}
/* get ready for next row */
if (mask != 128)
src++;
}
if (count + width >= SWRAST_MAX_WIDTH || row + 1 == height) {
/* flush the span */
span.end = count;
_swrast_write_rgba_span(ctx, &span);
span.end = 0;
count = 0;
}
}
swrast_render_finish(ctx);
_mesa_unmap_pbo_source(ctx, unpack);
}
#if 0
/*
* XXX this is another way to implement Bitmap. Use horizontal runs of
* fragments, initializing the mask array to indicate which fragments to
* draw or skip.
*/
void
_swrast_Bitmap( struct gl_context *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLint row, col;
SWspan span;
assert(ctx->RenderMode == GL_RENDER);
assert(bitmap);
swrast_render_start(ctx);
if (SWRAST_CONTEXT(ctx)->NewState)
_swrast_validate_derived( ctx );
INIT_SPAN(span, GL_BITMAP);
span.end = width;
span.arrayMask = SPAN_MASK;
_swrast_span_default_attribs(ctx, &span);
/*span.arrayMask |= SPAN_MASK;*/ /* we'll init span.mask[] */
span.x = px;
span.y = py;
/*span.end = width;*/
for (row=0; row<height; row++, span.y++) {
const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
if (unpack->LsbFirst) {
/* Lsb first */
GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
for (col=0; col<width; col++) {
span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
if (mask == 128U) {
src++;
mask = 1U;
}
else {
mask = mask << 1;
}
}
_swrast_write_rgba_span(ctx, &span);
/* get ready for next row */
if (mask != 1)
src++;
}
else {
/* Msb first */
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
for (col=0; col<width; col++) {
span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
if (mask == 1U) {
src++;
mask = 128U;
}
else {
mask = mask >> 1;
}
}
_swrast_write_rgba_span(ctx, &span);
/* get ready for next row */
if (mask != 128)
src++;
}
}
swrast_render_finish(ctx);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,45 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_BLEND_H
#define S_BLEND_H
#include "main/glheader.h"
#include "s_span.h"
struct gl_context;
struct gl_renderbuffer;
extern void
_swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span);
extern void
_swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType);
#endif

View File

@ -1,816 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/condrender.h"
#include "main/image.h"
#include "main/macros.h"
#include "main/format_unpack.h"
#include "main/format_pack.h"
#include "main/condrender.h"
#include "s_context.h"
#define ABS(X) ((X) < 0 ? -(X) : (X))
/**
* Generate a row resampler function for GL_NEAREST mode.
*/
#define RESAMPLE(NAME, PIXELTYPE, SIZE) \
static void \
NAME(GLint srcWidth, GLint dstWidth, \
const GLvoid *srcBuffer, GLvoid *dstBuffer, \
GLboolean flip) \
{ \
const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
PIXELTYPE *dst = (PIXELTYPE *) dstBuffer; \
GLint dstCol; \
\
if (flip) { \
for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
GLint srcCol = (dstCol * srcWidth) / dstWidth; \
assert(srcCol >= 0); \
assert(srcCol < srcWidth); \
srcCol = srcWidth - 1 - srcCol; /* flip */ \
if (SIZE == 1) { \
dst[dstCol] = src[srcCol]; \
} \
else if (SIZE == 2) { \
dst[dstCol*2+0] = src[srcCol*2+0]; \
dst[dstCol*2+1] = src[srcCol*2+1]; \
} \
else if (SIZE == 4) { \
dst[dstCol*4+0] = src[srcCol*4+0]; \
dst[dstCol*4+1] = src[srcCol*4+1]; \
dst[dstCol*4+2] = src[srcCol*4+2]; \
dst[dstCol*4+3] = src[srcCol*4+3]; \
} \
} \
} \
else { \
for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
GLint srcCol = (dstCol * srcWidth) / dstWidth; \
assert(srcCol >= 0); \
assert(srcCol < srcWidth); \
if (SIZE == 1) { \
dst[dstCol] = src[srcCol]; \
} \
else if (SIZE == 2) { \
dst[dstCol*2+0] = src[srcCol*2+0]; \
dst[dstCol*2+1] = src[srcCol*2+1]; \
} \
else if (SIZE == 4) { \
dst[dstCol*4+0] = src[srcCol*4+0]; \
dst[dstCol*4+1] = src[srcCol*4+1]; \
dst[dstCol*4+2] = src[srcCol*4+2]; \
dst[dstCol*4+3] = src[srcCol*4+3]; \
} \
} \
} \
}
/**
* Resamplers for 1, 2, 4, 8 and 16-byte pixels.
*/
RESAMPLE(resample_row_1, GLubyte, 1)
RESAMPLE(resample_row_2, GLushort, 1)
RESAMPLE(resample_row_4, GLuint, 1)
RESAMPLE(resample_row_8, GLuint, 2)
RESAMPLE(resample_row_16, GLuint, 4)
/**
* Blit color, depth or stencil with GL_NEAREST filtering.
*/
static void
blit_nearest(struct gl_context *ctx,
struct gl_framebuffer *readFb,
struct gl_framebuffer *drawFb,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield buffer)
{
struct gl_renderbuffer *readRb, *drawRb = NULL;
struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL;
GLuint numDrawBuffers = 0;
GLuint i;
const GLint srcWidth = ABS(srcX1 - srcX0);
const GLint dstWidth = ABS(dstX1 - dstX0);
const GLint srcHeight = ABS(srcY1 - srcY0);
const GLint dstHeight = ABS(dstY1 - dstY0);
const GLint srcXpos = MIN2(srcX0, srcX1);
const GLint srcYpos = MIN2(srcY0, srcY1);
const GLint dstXpos = MIN2(dstX0, dstX1);
const GLint dstYpos = MIN2(dstY0, dstY1);
const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
enum mode {
DIRECT,
UNPACK_RGBA_FLOAT,
UNPACK_Z_FLOAT,
UNPACK_Z_INT,
UNPACK_S,
} mode = DIRECT;
GLubyte *srcMap, *dstMap;
GLint srcRowStride, dstRowStride;
GLint dstRow;
GLint pixelSize = 0;
GLvoid *srcBuffer, *dstBuffer;
GLint prevY = -1;
typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
const GLvoid *srcBuffer, GLvoid *dstBuffer,
GLboolean flip);
resample_func resampleRow;
switch (buffer) {
case GL_COLOR_BUFFER_BIT:
readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex];
readRb = readFb->_ColorReadBuffer;
numDrawBuffers = drawFb->_NumColorDrawBuffers;
break;
case GL_DEPTH_BUFFER_BIT:
readAtt = &readFb->Attachment[BUFFER_DEPTH];
drawAtt = &drawFb->Attachment[BUFFER_DEPTH];
readRb = readAtt->Renderbuffer;
drawRb = drawAtt->Renderbuffer;
numDrawBuffers = 1;
/* Note that for depth/stencil, the formats of src/dst must match. By
* using the core helpers for pack/unpack, we avoid needing to handle
* masking for things like DEPTH copies of Z24S8.
*/
if (readRb->Format == MESA_FORMAT_Z_FLOAT32 ||
readRb->Format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
mode = UNPACK_Z_FLOAT;
} else {
mode = UNPACK_Z_INT;
}
pixelSize = 4;
break;
case GL_STENCIL_BUFFER_BIT:
readAtt = &readFb->Attachment[BUFFER_STENCIL];
drawAtt = &drawFb->Attachment[BUFFER_STENCIL];
readRb = readAtt->Renderbuffer;
drawRb = drawAtt->Renderbuffer;
numDrawBuffers = 1;
mode = UNPACK_S;
pixelSize = 1;
break;
default:
_mesa_problem(ctx, "unexpected buffer in blit_nearest()");
return;
}
/* allocate the src/dst row buffers */
srcBuffer = malloc(MAX_PIXEL_BYTES * srcWidth);
dstBuffer = malloc(MAX_PIXEL_BYTES * dstWidth);
if (!srcBuffer || !dstBuffer)
goto fail_no_memory;
/* Blit to all the draw buffers */
for (i = 0; i < numDrawBuffers; i++) {
if (buffer == GL_COLOR_BUFFER_BIT) {
gl_buffer_index idx = drawFb->_ColorDrawBufferIndexes[i];
if (idx == BUFFER_NONE)
continue;
drawAtt = &drawFb->Attachment[idx];
drawRb = drawAtt->Renderbuffer;
if (!drawRb)
continue;
if (readRb->Format == drawRb->Format) {
mode = DIRECT;
pixelSize = _mesa_get_format_bytes(readRb->Format);
} else {
mode = UNPACK_RGBA_FLOAT;
pixelSize = 16;
}
}
/* choose row resampler */
switch (pixelSize) {
case 1:
resampleRow = resample_row_1;
break;
case 2:
resampleRow = resample_row_2;
break;
case 4:
resampleRow = resample_row_4;
break;
case 8:
resampleRow = resample_row_8;
break;
case 16:
resampleRow = resample_row_16;
break;
default:
_mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
pixelSize);
goto fail;
}
if ((readRb == drawRb) ||
(readAtt->Texture && drawAtt->Texture &&
(readAtt->Texture == drawAtt->Texture))) {
/* map whole buffer for read/write */
/* XXX we could be clever and just map the union region of the
* source and dest rects.
*/
GLubyte *map;
GLint rowStride;
GLint formatSize = _mesa_get_format_bytes(readRb->Format);
ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
readRb->Width, readRb->Height,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
&map, &rowStride, readFb->FlipY);
if (!map) {
goto fail_no_memory;
}
srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
dstMap = map + dstYpos * rowStride + dstXpos * formatSize;
/* this handles overlapping copies */
if (srcY0 < dstY0) {
/* copy in reverse (top->down) order */
srcMap += rowStride * (readRb->Height - 1);
dstMap += rowStride * (readRb->Height - 1);
srcRowStride = -rowStride;
dstRowStride = -rowStride;
}
else {
/* copy in normal (bottom->up) order */
srcRowStride = rowStride;
dstRowStride = rowStride;
}
}
else {
/* different src/dst buffers */
ctx->Driver.MapRenderbuffer(ctx, readRb,
srcXpos, srcYpos,
srcWidth, srcHeight,
GL_MAP_READ_BIT, &srcMap, &srcRowStride,
readFb->FlipY);
if (!srcMap) {
goto fail_no_memory;
}
ctx->Driver.MapRenderbuffer(ctx, drawRb,
dstXpos, dstYpos,
dstWidth, dstHeight,
GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
drawFb->FlipY);
if (!dstMap) {
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
goto fail_no_memory;
}
}
for (dstRow = 0; dstRow < dstHeight; dstRow++) {
GLfloat srcRowF = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
GLint srcRow = lroundf(srcRowF);
GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
assert(srcRow >= 0);
assert(srcRow < srcHeight);
if (invertY) {
srcRow = srcHeight - 1 - srcRow;
}
/* get pixel row from source and resample to match dest width */
if (prevY != srcRow) {
GLubyte *srcRowStart = srcMap + srcRowStride * srcRow;
switch (mode) {
case DIRECT:
memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth);
break;
case UNPACK_RGBA_FLOAT:
_mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart,
srcBuffer);
break;
case UNPACK_Z_FLOAT:
_mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart,
srcBuffer);
break;
case UNPACK_Z_INT:
_mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart,
srcBuffer);
break;
case UNPACK_S:
_mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth,
srcRowStart, srcBuffer);
break;
}
resampleRow(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
prevY = srcRow;
}
/* store pixel row in destination */
switch (mode) {
case DIRECT:
memcpy(dstRowStart, dstBuffer, pixelSize * dstWidth);
break;
case UNPACK_RGBA_FLOAT:
_mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
dstRowStart);
break;
case UNPACK_Z_FLOAT:
_mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer,
dstRowStart);
break;
case UNPACK_Z_INT:
_mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer,
dstRowStart);
break;
case UNPACK_S:
_mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer,
dstRowStart);
break;
}
}
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
if (drawRb != readRb) {
ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
}
}
fail:
free(srcBuffer);
free(dstBuffer);
return;
fail_no_memory:
free(srcBuffer);
free(dstBuffer);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBuffer");
}
#define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
static inline GLfloat
lerp_2d(GLfloat a, GLfloat b,
GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
{
const GLfloat temp0 = LERP(a, v00, v10);
const GLfloat temp1 = LERP(a, v01, v11);
return LERP(b, temp0, temp1);
}
/**
* Bilinear interpolation of two source rows.
* GLubyte pixels.
*/
static void
resample_linear_row_ub(GLint srcWidth, GLint dstWidth,
const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
{
const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
GLint dstCol;
for (dstCol = 0; dstCol < dstWidth; dstCol++) {
const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
GLint srcCol0 = MAX2(0, util_ifloor(srcCol));
GLint srcCol1 = srcCol0 + 1;
GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
GLfloat red, green, blue, alpha;
assert(srcCol0 < srcWidth);
assert(srcCol1 <= srcWidth);
if (srcCol1 == srcWidth) {
/* last column fudge */
srcCol1--;
colWeight = 0.0;
}
if (flip) {
srcCol0 = srcWidth - 1 - srcCol0;
srcCol1 = srcWidth - 1 - srcCol1;
}
red = lerp_2d(colWeight, rowWeight,
srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
green = lerp_2d(colWeight, rowWeight,
srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
blue = lerp_2d(colWeight, rowWeight,
srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
alpha = lerp_2d(colWeight, rowWeight,
srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
dstColor[dstCol][RCOMP] = util_ifloor(red);
dstColor[dstCol][GCOMP] = util_ifloor(green);
dstColor[dstCol][BCOMP] = util_ifloor(blue);
dstColor[dstCol][ACOMP] = util_ifloor(alpha);
}
}
/**
* Bilinear interpolation of two source rows. floating point pixels.
*/
static void
resample_linear_row_float(GLint srcWidth, GLint dstWidth,
const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
{
const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4]) srcBuffer0;
const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4]) srcBuffer1;
GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer;
GLint dstCol;
for (dstCol = 0; dstCol < dstWidth; dstCol++) {
const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
GLint srcCol0 = MAX2(0, util_ifloor(srcCol));
GLint srcCol1 = srcCol0 + 1;
GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
GLfloat red, green, blue, alpha;
assert(srcCol0 < srcWidth);
assert(srcCol1 <= srcWidth);
if (srcCol1 == srcWidth) {
/* last column fudge */
srcCol1--;
colWeight = 0.0;
}
if (flip) {
srcCol0 = srcWidth - 1 - srcCol0;
srcCol1 = srcWidth - 1 - srcCol1;
}
red = lerp_2d(colWeight, rowWeight,
srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
green = lerp_2d(colWeight, rowWeight,
srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
blue = lerp_2d(colWeight, rowWeight,
srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
alpha = lerp_2d(colWeight, rowWeight,
srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
dstColor[dstCol][RCOMP] = red;
dstColor[dstCol][GCOMP] = green;
dstColor[dstCol][BCOMP] = blue;
dstColor[dstCol][ACOMP] = alpha;
}
}
/**
* Bilinear filtered blit (color only, non-integer values).
*/
static void
blit_linear(struct gl_context *ctx,
struct gl_framebuffer *readFb,
struct gl_framebuffer *drawFb,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
{
struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer;
struct gl_renderbuffer_attachment *readAtt =
&readFb->Attachment[readFb->_ColorReadBufferIndex];
const GLint srcWidth = ABS(srcX1 - srcX0);
const GLint dstWidth = ABS(dstX1 - dstX0);
const GLint srcHeight = ABS(srcY1 - srcY0);
const GLint dstHeight = ABS(dstY1 - dstY0);
const GLint srcXpos = MIN2(srcX0, srcX1);
const GLint srcYpos = MIN2(srcY0, srcY1);
const GLint dstXpos = MIN2(dstX0, dstX1);
const GLint dstYpos = MIN2(dstY0, dstY1);
const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
GLint dstRow;
GLint pixelSize;
GLvoid *srcBuffer0, *srcBuffer1;
GLint srcBufferY0 = -1, srcBufferY1 = -1;
GLvoid *dstBuffer;
mesa_format readFormat = _mesa_get_srgb_format_linear(readRb->Format);
GLuint bpp = _mesa_get_format_bytes(readFormat);
GLenum pixelType;
GLubyte *srcMap, *dstMap;
GLint srcRowStride, dstRowStride;
GLuint i;
/* Determine datatype for resampling */
if (_mesa_get_format_max_bits(readFormat) == 8 &&
_mesa_get_format_datatype(readFormat) == GL_UNSIGNED_NORMALIZED) {
pixelType = GL_UNSIGNED_BYTE;
pixelSize = 4 * sizeof(GLubyte);
}
else {
pixelType = GL_FLOAT;
pixelSize = 4 * sizeof(GLfloat);
}
/* Allocate the src/dst row buffers.
* Keep two adjacent src rows around for bilinear sampling.
*/
srcBuffer0 = malloc(pixelSize * srcWidth);
srcBuffer1 = malloc(pixelSize * srcWidth);
dstBuffer = malloc(pixelSize * dstWidth);
if (!srcBuffer0 || !srcBuffer1 || !dstBuffer) {
goto fail_no_memory;
}
for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
gl_buffer_index idx = drawFb->_ColorDrawBufferIndexes[i];
struct gl_renderbuffer_attachment *drawAtt;
struct gl_renderbuffer *drawRb;
mesa_format drawFormat;
if (idx == BUFFER_NONE)
continue;
drawAtt = &drawFb->Attachment[idx];
drawRb = drawAtt->Renderbuffer;
if (!drawRb)
continue;
drawFormat = _mesa_get_srgb_format_linear(drawRb->Format);
/*
* Map src / dst renderbuffers
*/
if ((readRb == drawRb) ||
(readAtt->Texture && drawAtt->Texture &&
(readAtt->Texture == drawAtt->Texture))) {
/* map whole buffer for read/write */
ctx->Driver.MapRenderbuffer(ctx, readRb,
0, 0, readRb->Width, readRb->Height,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
&srcMap, &srcRowStride,
readFb->FlipY);
if (!srcMap) {
goto fail_no_memory;
}
dstMap = srcMap;
dstRowStride = srcRowStride;
}
else {
/* different src/dst buffers */
/* XXX with a bit of work we could just map the regions to be
* read/written instead of the whole buffers.
*/
ctx->Driver.MapRenderbuffer(ctx, readRb,
0, 0, readRb->Width, readRb->Height,
GL_MAP_READ_BIT, &srcMap, &srcRowStride,
readFb->FlipY);
if (!srcMap) {
goto fail_no_memory;
}
ctx->Driver.MapRenderbuffer(ctx, drawRb,
0, 0, drawRb->Width, drawRb->Height,
GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
drawFb->FlipY);
if (!dstMap) {
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
goto fail_no_memory;
}
}
for (dstRow = 0; dstRow < dstHeight; dstRow++) {
const GLint dstY = dstYpos + dstRow;
GLfloat srcRow = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
GLint srcRow0 = MAX2(0, util_ifloor(srcRow));
GLint srcRow1 = srcRow0 + 1;
GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
if (srcRow1 == srcHeight) {
/* last row fudge */
srcRow1 = srcRow0;
rowWeight = 0.0;
}
if (invertY) {
srcRow0 = srcHeight - 1 - srcRow0;
srcRow1 = srcHeight - 1 - srcRow1;
}
srcY0 = srcYpos + srcRow0;
srcY1 = srcYpos + srcRow1;
/* get the two source rows */
if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
/* use same source row buffers again */
}
else if (srcY0 == srcBufferY1) {
/* move buffer1 into buffer0 by swapping pointers */
GLvoid *tmp = srcBuffer0;
srcBuffer0 = srcBuffer1;
srcBuffer1 = tmp;
/* get y1 row */
{
GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
if (pixelType == GL_UNSIGNED_BYTE) {
_mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
src, srcBuffer1);
}
else {
_mesa_unpack_rgba_row(readFormat, srcWidth,
src, srcBuffer1);
}
}
srcBufferY0 = srcY0;
srcBufferY1 = srcY1;
}
else {
/* get both new rows */
{
GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp;
GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
if (pixelType == GL_UNSIGNED_BYTE) {
_mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
src0, srcBuffer0);
_mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
src1, srcBuffer1);
}
else {
_mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0);
_mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1);
}
}
srcBufferY0 = srcY0;
srcBufferY1 = srcY1;
}
if (pixelType == GL_UNSIGNED_BYTE) {
resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
dstBuffer, invertX, rowWeight);
}
else {
resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
dstBuffer, invertX, rowWeight);
}
/* store pixel row in destination */
{
GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp;
if (pixelType == GL_UNSIGNED_BYTE) {
_mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
}
else {
_mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
}
}
}
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
if (drawRb != readRb) {
ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
}
}
free(srcBuffer0);
free(srcBuffer1);
free(dstBuffer);
return;
fail_no_memory:
free(srcBuffer0);
free(srcBuffer1);
free(dstBuffer);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
}
/**
* Software fallback for glBlitFramebufferEXT().
*/
void
_swrast_BlitFramebuffer(struct gl_context *ctx,
struct gl_framebuffer *readFb,
struct gl_framebuffer *drawFb,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
static const GLbitfield buffers[3] = {
GL_COLOR_BUFFER_BIT,
GL_DEPTH_BUFFER_BIT,
GL_STENCIL_BUFFER_BIT
};
static const GLenum buffer_enums[3] = {
GL_COLOR,
GL_DEPTH,
GL_STENCIL,
};
GLint i;
/* Page 679 of OpenGL 4.4 spec says:
* "Added BlitFramebuffer to commands affected by conditional rendering in
* section 10.10 (Bug 9562)."
*/
if (!_mesa_check_conditional_render(ctx))
return; /* Do not blit */
if (!_mesa_clip_blit(ctx, readFb, drawFb, &srcX0, &srcY0, &srcX1, &srcY1,
&dstX0, &dstY0, &dstX1, &dstY1)) {
return;
}
if (SWRAST_CONTEXT(ctx)->NewState)
_swrast_validate_derived(ctx);
/* First, try covering whatever buffers possible using the fast 1:1 copy
* path.
*/
if (srcX1 - srcX0 == dstX1 - dstX0 &&
srcY1 - srcY0 == dstY1 - dstY0 &&
srcX0 < srcX1 &&
srcY0 < srcY1 &&
dstX0 < dstX1 &&
dstY0 < dstY1) {
for (i = 0; i < 3; i++) {
if (mask & buffers[i]) {
if (swrast_fast_copy_pixels(ctx,
readFb, drawFb,
srcX0, srcY0,
srcX1 - srcX0, srcY1 - srcY0,
dstX0, dstY0,
buffer_enums[i])) {
mask &= ~buffers[i];
}
}
}
if (!mask)
return;
}
if (filter == GL_NEAREST) {
for (i = 0; i < 3; i++) {
if (mask & buffers[i]) {
blit_nearest(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1, buffers[i]);
}
}
}
else {
assert(filter == GL_LINEAR);
if (mask & GL_COLOR_BUFFER_BIT) { /* depth/stencil not allowed */
blit_linear(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1);
}
}
}

View File

@ -1,128 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Types, macros, etc for the GLchan datatype.
* The swrast module is kind of hard-coded for 8bpp color channels but
* may be recompiled to use 16- or 32-bit color channels. But that
* feature is seldom used and is likely broken in various ways.
*/
#ifndef U_CHAN_H
#define U_CHAN_H
#include "main/config.h"
/**
* Default bits per color channel: 8, 16 or 32
*/
#ifndef CHAN_BITS
#define CHAN_BITS 8
#endif
/**
* Color channel data type.
*/
#if CHAN_BITS == 8
typedef GLubyte GLchan;
#define CHAN_MAX 255
#define CHAN_MAXF 255.0F
#define CHAN_TYPE GL_UNSIGNED_BYTE
#elif CHAN_BITS == 16
typedef GLushort GLchan;
#define CHAN_MAX 65535
#define CHAN_MAXF 65535.0F
#define CHAN_TYPE GL_UNSIGNED_SHORT
#elif CHAN_BITS == 32
typedef GLfloat GLchan;
#define CHAN_MAX 1.0
#define CHAN_MAXF 1.0F
#define CHAN_TYPE GL_FLOAT
#else
#error "illegal number of color channel bits"
#endif
#if CHAN_BITS == 8
#define CHAN_TO_UBYTE(c) (c)
#define CHAN_TO_USHORT(c) (((c) << 8) | (c))
#define CHAN_TO_SHORT(c) (((c) << 7) | ((c) >> 1))
#define CHAN_TO_FLOAT(c) UBYTE_TO_FLOAT(c)
#define CLAMPED_FLOAT_TO_CHAN(c, f) CLAMPED_FLOAT_TO_UBYTE(c, f)
#define UNCLAMPED_FLOAT_TO_CHAN(c, f) UNCLAMPED_FLOAT_TO_UBYTE(c, f)
#define COPY_CHAN4(DST, SRC) COPY_4UBV(DST, SRC)
#elif CHAN_BITS == 16
#define CHAN_TO_UBYTE(c) ((c) >> 8)
#define CHAN_TO_USHORT(c) (c)
#define CHAN_TO_SHORT(c) ((c) >> 1)
#define CHAN_TO_FLOAT(c) ((GLfloat) ((c) * (1.0 / CHAN_MAXF)))
#define CLAMPED_FLOAT_TO_CHAN(c, f) CLAMPED_FLOAT_TO_USHORT(c, f)
#define UNCLAMPED_FLOAT_TO_CHAN(c, f) UNCLAMPED_FLOAT_TO_USHORT(c, f)
#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC)
#elif CHAN_BITS == 32
#define CHAN_TO_UBYTE(c) FLOAT_TO_UBYTE(c)
#define CHAN_TO_USHORT(c) ((GLushort) (SATURATE((c)) * 65535.0))
#define CHAN_TO_SHORT(c) ((GLshort) (SATURATE((c)) * 32767.0))
#define CHAN_TO_FLOAT(c) (c)
#define CLAMPED_FLOAT_TO_CHAN(c, f) c = (f)
#define UNCLAMPED_FLOAT_TO_CHAN(c, f) c = (f)
#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC)
#else
#error unexpected CHAN_BITS size
#endif
/**
* Convert 4 floats to GLchan values.
* \param dst pointer to destination GLchan[4] array.
* \param f pointer to source GLfloat[4] array.
*/
#define UNCLAMPED_FLOAT_TO_RGBA_CHAN(dst, f) \
do { \
UNCLAMPED_FLOAT_TO_CHAN((dst)[0], (f)[0]); \
UNCLAMPED_FLOAT_TO_CHAN((dst)[1], (f)[1]); \
UNCLAMPED_FLOAT_TO_CHAN((dst)[2], (f)[2]); \
UNCLAMPED_FLOAT_TO_CHAN((dst)[3], (f)[3]); \
} while (0)
#endif /* U_CHAN_H */

View File

@ -1,333 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/accum.h"
#include "main/condrender.h"
#include "main/format_pack.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "s_context.h"
#include "s_depth.h"
#include "s_stencil.h"
/**
* Convert a boolean color mask to a packed color where each channel of
* the packed value at dst will be 0 or ~0 depending on the colorMask.
*/
static void
_pack_colormask(mesa_format format, const uint8_t colorMask[4], void *dst)
{
float maskColor[4];
switch (_mesa_get_format_datatype(format)) {
case GL_UNSIGNED_NORMALIZED:
/* simple: 1.0 will convert to ~0 in the right bit positions */
maskColor[0] = colorMask[0] ? 1.0f : 0.0f;
maskColor[1] = colorMask[1] ? 1.0f : 0.0f;
maskColor[2] = colorMask[2] ? 1.0f : 0.0f;
maskColor[3] = colorMask[3] ? 1.0f : 0.0f;
_mesa_pack_float_rgba_row(format, 1,
(const float (*)[4]) maskColor, dst);
break;
case GL_SIGNED_NORMALIZED:
case GL_FLOAT:
/* These formats are harder because it's hard to know the floating
* point values that will convert to ~0 for each color channel's bits.
* This solution just generates a non-zero value for each color channel
* then fixes up the non-zero values to be ~0.
* Note: we'll need to add special case code if we ever have to deal
* with formats with unequal color channel sizes, like R11_G11_B10.
* We issue a warning below for channel sizes other than 8,16,32.
*/
{
uint32_t bits = _mesa_get_format_max_bits(format); /* bits per chan */
uint32_t bytes = _mesa_get_format_bytes(format);
uint32_t i;
/* this should put non-zero values into the channels of dst */
maskColor[0] = colorMask[0] ? -1.0f : 0.0f;
maskColor[1] = colorMask[1] ? -1.0f : 0.0f;
maskColor[2] = colorMask[2] ? -1.0f : 0.0f;
maskColor[3] = colorMask[3] ? -1.0f : 0.0f;
_mesa_pack_float_rgba_row(format, 1,
(const float (*)[4]) maskColor, dst);
/* fix-up the dst channels by converting non-zero values to ~0 */
if (bits == 8) {
uint8_t *d = (uint8_t *) dst;
for (i = 0; i < bytes; i++) {
d[i] = d[i] ? 0xff : 0x0;
}
}
else if (bits == 16) {
uint16_t *d = (uint16_t *) dst;
for (i = 0; i < bytes / 2; i++) {
d[i] = d[i] ? 0xffff : 0x0;
}
}
else if (bits == 32) {
uint32_t *d = (uint32_t *) dst;
for (i = 0; i < bytes / 4; i++) {
d[i] = d[i] ? 0xffffffffU : 0x0;
}
}
else {
unreachable("unexpected size in _mesa_pack_colormask()");
}
}
break;
default:
unreachable("unexpected format data type in gen_color_mask()");
}
}
/**
* Clear an rgba color buffer with masking if needed.
*/
static void
clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb,
const GLubyte colorMask[4])
{
const GLint x = ctx->DrawBuffer->_Xmin;
const GLint y = ctx->DrawBuffer->_Ymin;
const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
const GLuint pixelSize = _mesa_get_format_bytes(rb->Format);
const GLboolean doMasking = (colorMask[0] == 0 ||
colorMask[1] == 0 ||
colorMask[2] == 0 ||
colorMask[3] == 0);
const GLfloat (*clearColor)[4] =
(const GLfloat (*)[4]) ctx->Color.ClearColor.f;
GLbitfield mapMode = GL_MAP_WRITE_BIT;
GLubyte *map;
GLint rowStride;
GLint i, j;
if (doMasking) {
/* we'll need to read buffer values too */
mapMode |= GL_MAP_READ_BIT;
}
/* map dest buffer */
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
mapMode, &map, &rowStride,
ctx->DrawBuffer->FlipY);
if (!map) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)");
return;
}
/* for 1, 2, 4-byte clearing */
#define SIMPLE_TYPE_CLEAR(TYPE) \
do { \
TYPE pixel, pixelMask; \
_mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel); \
if (doMasking) { \
_pack_colormask(rb->Format, colorMask, &pixelMask); \
pixel &= pixelMask; \
pixelMask = ~pixelMask; \
} \
for (i = 0; i < height; i++) { \
TYPE *row = (TYPE *) map; \
if (doMasking) { \
for (j = 0; j < width; j++) { \
row[j] = (row[j] & pixelMask) | pixel; \
} \
} \
else { \
for (j = 0; j < width; j++) { \
row[j] = pixel; \
} \
} \
map += rowStride; \
} \
} while (0)
/* for 3, 6, 8, 12, 16-byte clearing */
#define MULTI_WORD_CLEAR(TYPE, N) \
do { \
TYPE pixel[N], pixelMask[N]; \
GLuint k; \
_mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel); \
if (doMasking) { \
_pack_colormask(rb->Format, colorMask, pixelMask); \
for (k = 0; k < N; k++) { \
pixel[k] &= pixelMask[k]; \
pixelMask[k] = ~pixelMask[k]; \
} \
} \
for (i = 0; i < height; i++) { \
TYPE *row = (TYPE *) map; \
if (doMasking) { \
for (j = 0; j < width; j++) { \
for (k = 0; k < N; k++) { \
row[j * N + k] = \
(row[j * N + k] & pixelMask[k]) | pixel[k]; \
} \
} \
} \
else { \
for (j = 0; j < width; j++) { \
for (k = 0; k < N; k++) { \
row[j * N + k] = pixel[k]; \
} \
} \
} \
map += rowStride; \
} \
} while(0)
switch (pixelSize) {
case 1:
SIMPLE_TYPE_CLEAR(GLubyte);
break;
case 2:
SIMPLE_TYPE_CLEAR(GLushort);
break;
case 3:
MULTI_WORD_CLEAR(GLubyte, 3);
break;
case 4:
SIMPLE_TYPE_CLEAR(GLuint);
break;
case 6:
MULTI_WORD_CLEAR(GLushort, 3);
break;
case 8:
MULTI_WORD_CLEAR(GLuint, 2);
break;
case 12:
MULTI_WORD_CLEAR(GLuint, 3);
break;
case 16:
MULTI_WORD_CLEAR(GLuint, 4);
break;
default:
_mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()");
}
/* unmap buffer */
ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
/**
* Clear the front/back/left/right/aux color buffers.
* This function is usually only called if the device driver can't
* clear its own color buffers for some reason (such as with masking).
*/
static void
clear_color_buffers(struct gl_context *ctx)
{
GLuint buf;
for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
/* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
* the framebuffer can be complete with some attachments be missing. In
* this case the _ColorDrawBuffers pointer will be NULL.
*/
if (rb == NULL)
continue;
const GLubyte colormask[4] = {
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xff : 0,
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xff : 0,
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xff : 0,
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xff : 0,
};
clear_rgba_buffer(ctx, rb, colormask);
}
}
/**
* Called via the device driver's ctx->Driver.Clear() function if the
* device driver can't clear one or more of the buffers itself.
* \param buffers bitfield of BUFFER_BIT_* values indicating which
* renderbuffers are to be cleared.
* \param all if GL_TRUE, clear whole buffer, else clear specified region.
*/
void
_swrast_Clear(struct gl_context *ctx, GLbitfield buffers)
{
const GLbitfield BUFFER_DS = BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL;
#ifdef DEBUG_FOO
{
const GLbitfield legalBits =
BUFFER_BIT_FRONT_LEFT |
BUFFER_BIT_FRONT_RIGHT |
BUFFER_BIT_BACK_LEFT |
BUFFER_BIT_BACK_RIGHT |
BUFFER_BIT_DEPTH |
BUFFER_BIT_STENCIL |
BUFFER_BIT_ACCUM;
assert((buffers & (~legalBits)) == 0);
}
#endif
if (!_mesa_check_conditional_render(ctx))
return; /* don't clear */
if (SWRAST_CONTEXT(ctx)->NewState)
_swrast_validate_derived(ctx);
if ((buffers & BUFFER_BITS_COLOR)
&& (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) {
clear_color_buffers(ctx);
}
if (buffers & BUFFER_BIT_ACCUM) {
_mesa_clear_accum_buffer(ctx);
}
if (buffers & BUFFER_DS) {
struct gl_renderbuffer *depthRb =
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
struct gl_renderbuffer *stencilRb =
ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
if ((buffers & BUFFER_DS) == BUFFER_DS && depthRb == stencilRb) {
/* clear depth and stencil together */
_swrast_clear_depth_stencil_buffer(ctx);
}
else {
/* clear depth, stencil separately */
if (buffers & BUFFER_BIT_DEPTH) {
_swrast_clear_depth_buffer(ctx);
}
if (buffers & BUFFER_BIT_STENCIL) {
_swrast_clear_stencil_buffer(ctx);
}
}
}
}

View File

@ -1,953 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com> Brian Paul
*/
#include "main/errors.h"
#include "main/bufferobj.h"
#include "main/mtypes.h"
#include "main/samplerobj.h"
#include "main/state.h"
#include "main/stencil.h"
#include "main/teximage.h"
#include "program/prog_parameter.h"
#include "program/prog_statevars.h"
#include "swrast.h"
#include "s_blend.h"
#include "s_context.h"
#include "s_lines.h"
#include "s_points.h"
#include "s_span.h"
#include "s_texfetch.h"
#include "s_triangle.h"
#include "s_texfilter.h"
/**
* Recompute the value of swrast->_RasterMask, etc. according to
* the current context. The _RasterMask field can be easily tested by
* drivers to determine certain basic GL state (does the primitive need
* stenciling, logic-op, fog, etc?).
*/
static void
_swrast_update_rasterflags( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLbitfield rasterMask = 0;
GLuint i;
if (ctx->Color.AlphaEnabled) rasterMask |= ALPHATEST_BIT;
if (ctx->Color.BlendEnabled) rasterMask |= BLEND_BIT;
if (ctx->Depth.Test) rasterMask |= DEPTH_BIT;
if (swrast->_FogEnabled) rasterMask |= FOG_BIT;
if (ctx->Scissor.EnableFlags) rasterMask |= CLIP_BIT;
if (_mesa_stencil_is_enabled(ctx)) rasterMask |= STENCIL_BIT;
for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
if (GET_COLORMASK(ctx->Color.ColorMask, i) != 0xf) {
rasterMask |= MASKING_BIT;
break;
}
}
if (ctx->Color.ColorLogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
if (ctx->Texture._MaxEnabledTexImageUnit >= 0) rasterMask |= TEXTURE_BIT;
if ( ctx->ViewportArray[0].X < 0
|| ctx->ViewportArray[0].X + ctx->ViewportArray[0].Width > (GLfloat) ctx->DrawBuffer->Width
|| ctx->ViewportArray[0].Y < 0
|| ctx->ViewportArray[0].Y + ctx->ViewportArray[0].Height > (GLfloat) ctx->DrawBuffer->Height) {
rasterMask |= CLIP_BIT;
}
if (ctx->Query.CurrentOcclusionObject)
rasterMask |= OCCLUSION_BIT;
/* If we're not drawing to exactly one color buffer set the
* MULTI_DRAW_BIT flag. Also set it if we're drawing to no
* buffers or the RGBA or CI mask disables all writes.
*/
if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
/* more than one color buffer designated for writing (or zero buffers) */
rasterMask |= MULTI_DRAW_BIT;
}
for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
if (GET_COLORMASK(ctx->Color.ColorMask, i) == 0) {
rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
break;
}
}
if (_swrast_use_fragment_program(ctx)) {
rasterMask |= FRAGPROG_BIT;
}
if (_mesa_ati_fragment_shader_enabled(ctx)) {
rasterMask |= ATIFRAGSHADER_BIT;
}
#if CHAN_TYPE == GL_FLOAT
if (ctx->Color.ClampFragmentColor == GL_TRUE) {
rasterMask |= CLAMPING_BIT;
}
#endif
SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask;
}
/**
* Examine polygon cull state to compute the _BackfaceCullSign field.
* _BackfaceCullSign will be 0 if no culling, -1 if culling back-faces,
* and 1 if culling front-faces. The Polygon FrontFace state also
* factors in.
*/
static void
_swrast_update_polygon( struct gl_context *ctx )
{
GLfloat backface_sign;
if (ctx->Polygon.CullFlag) {
switch (ctx->Polygon.CullFaceMode) {
case GL_BACK:
backface_sign = -1.0F;
break;
case GL_FRONT:
backface_sign = 1.0F;
break;
case GL_FRONT_AND_BACK:
FALLTHROUGH;
default:
backface_sign = 0.0F;
}
}
else {
backface_sign = 0.0F;
}
SWRAST_CONTEXT(ctx)->_BackfaceCullSign = backface_sign;
/* This is for front/back-face determination, but not for culling */
SWRAST_CONTEXT(ctx)->_BackfaceSign
= (ctx->Polygon.FrontFace == GL_CW) ? -1.0F : 1.0F;
}
/**
* Update the _PreferPixelFog field to indicate if we need to compute
* fog blend factors (from the fog coords) per-fragment.
*/
static void
_swrast_update_fog_hint( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
swrast->_PreferPixelFog = (!swrast->AllowVertexFog ||
_swrast_use_fragment_program(ctx) ||
(ctx->Hint.Fog == GL_NICEST &&
swrast->AllowPixelFog));
}
/**
* Update the swrast->_TextureCombinePrimary flag.
*/
static void
_swrast_update_texture_env( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint i;
swrast->_TextureCombinePrimary = GL_FALSE;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
const struct gl_tex_env_combine_state *combine =
ctx->Texture.FixedFuncUnit[i]._CurrentCombine;
GLuint term;
for (term = 0; term < combine->_NumArgsRGB; term++) {
if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) {
swrast->_TextureCombinePrimary = GL_TRUE;
return;
}
if (combine->SourceA[term] == GL_PRIMARY_COLOR) {
swrast->_TextureCombinePrimary = GL_TRUE;
return;
}
}
}
}
/**
* Determine if we can defer texturing/shading until after Z/stencil
* testing. This potentially allows us to skip texturing/shading for
* lots of fragments.
*/
static void
_swrast_update_deferred_texture(struct gl_context *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (ctx->Color.AlphaEnabled) {
/* alpha test depends on post-texture/shader colors */
swrast->_DeferredTexture = GL_FALSE;
}
else {
GLboolean use_fprog = _swrast_use_fragment_program(ctx);
const struct gl_program *fprog = ctx->FragmentProgram._Current;
if (use_fprog &&
(fprog->info.outputs_written & (1 << FRAG_RESULT_DEPTH))) {
/* Z comes from fragment program/shader */
swrast->_DeferredTexture = GL_FALSE;
}
else if (use_fprog && fprog->info.fs.uses_discard) {
swrast->_DeferredTexture = GL_FALSE;
}
else if (ctx->Query.CurrentOcclusionObject) {
/* occlusion query depends on shader discard/kill results */
swrast->_DeferredTexture = GL_FALSE;
}
else {
swrast->_DeferredTexture = GL_TRUE;
}
}
}
/**
* Update swrast->_FogColor and swrast->_FogEnable values.
*/
static void
_swrast_update_fog_state( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const struct gl_program *fp = ctx->FragmentProgram._Current;
assert(fp == NULL || fp->Target == GL_FRAGMENT_PROGRAM_ARB);
(void) fp; /* silence unused var warning */
/* determine if fog is needed, and if so, which fog mode */
swrast->_FogEnabled = (!_swrast_use_fragment_program(ctx) &&
ctx->Fog.Enabled);
}
/**
* Update state for running fragment programs. Basically, load the
* program parameters with current state values.
*/
static void
_swrast_update_fragment_program(struct gl_context *ctx, GLbitfield newState)
{
if (!_swrast_use_fragment_program(ctx))
return;
_mesa_load_state_parameters(ctx,
ctx->FragmentProgram._Current->Parameters);
}
/**
* See if we can do early diffuse+specular (primary+secondary) color
* add per vertex instead of per-fragment.
*/
static void
_swrast_update_specular_vertex_add(struct gl_context *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLboolean separateSpecular = ctx->Fog.ColorSumEnabled ||
(ctx->Light.Enabled &&
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR);
swrast->SpecularVertexAdd = (separateSpecular
&& ctx->Texture._MaxEnabledTexImageUnit == -1
&& !_swrast_use_fragment_program(ctx)
&& !_mesa_ati_fragment_shader_enabled(ctx));
}
#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \
_NEW_PROGRAM_CONSTANTS | \
_NEW_TEXTURE | \
_NEW_HINT | \
_NEW_POLYGON )
/* State referenced by _swrast_choose_triangle, _swrast_choose_line.
*/
#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED | \
_NEW_RENDERMODE| \
_NEW_POLYGON| \
_NEW_DEPTH| \
_NEW_STENCIL| \
_NEW_COLOR| \
_NEW_TEXTURE| \
_SWRAST_NEW_RASTERMASK| \
_NEW_LIGHT| \
_NEW_FOG | \
_MESA_NEW_SEPARATE_SPECULAR)
#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED | \
_NEW_RENDERMODE| \
_NEW_LINE| \
_NEW_TEXTURE| \
_NEW_LIGHT| \
_NEW_FOG| \
_NEW_DEPTH | \
_MESA_NEW_SEPARATE_SPECULAR)
#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED | \
_NEW_RENDERMODE | \
_NEW_POINT | \
_NEW_TEXTURE | \
_NEW_LIGHT | \
_NEW_FOG | \
_MESA_NEW_SEPARATE_SPECULAR)
#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE
#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE
#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR
/**
* Stub for swrast->Triangle to select a true triangle function
* after a state change.
*/
static void
_swrast_validate_triangle( struct gl_context *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2 )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
_swrast_validate_derived( ctx );
swrast->choose_triangle( ctx );
assert(swrast->Triangle);
if (swrast->SpecularVertexAdd) {
/* separate specular color, but no texture */
swrast->SpecTriangle = swrast->Triangle;
swrast->Triangle = _swrast_add_spec_terms_triangle;
}
swrast->Triangle( ctx, v0, v1, v2 );
}
/**
* Called via swrast->Line. Examine current GL state and choose a software
* line routine. Then call it.
*/
static void
_swrast_validate_line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
_swrast_validate_derived( ctx );
swrast->choose_line( ctx );
assert(swrast->Line);
if (swrast->SpecularVertexAdd) {
swrast->SpecLine = swrast->Line;
swrast->Line = _swrast_add_spec_terms_line;
}
swrast->Line( ctx, v0, v1 );
}
/**
* Called via swrast->Point. Examine current GL state and choose a software
* point routine. Then call it.
*/
static void
_swrast_validate_point( struct gl_context *ctx, const SWvertex *v0 )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
_swrast_validate_derived( ctx );
swrast->choose_point( ctx );
if (swrast->SpecularVertexAdd) {
swrast->SpecPoint = swrast->Point;
swrast->Point = _swrast_add_spec_terms_point;
}
swrast->Point( ctx, v0 );
}
/**
* Called via swrast->BlendFunc. Examine GL state to choose a blending
* function, then call it.
*/
static void
_swrast_validate_blend_func(struct gl_context *ctx, GLuint n, const GLubyte mask[],
GLvoid *src, const GLvoid *dst,
GLenum chanType )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
_swrast_validate_derived( ctx ); /* why is this needed? */
_swrast_choose_blend_func( ctx, chanType );
swrast->BlendFunc( ctx, n, mask, src, dst, chanType );
}
static void
_swrast_sleep( struct gl_context *ctx, GLbitfield new_state )
{
(void) ctx; (void) new_state;
}
static void
_swrast_invalidate_state( struct gl_context *ctx, GLbitfield new_state )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint i;
swrast->NewState |= new_state;
/* After 10 statechanges without any swrast functions being called,
* put the module to sleep.
*/
if (++swrast->StateChanges > 10) {
swrast->InvalidateState = _swrast_sleep;
swrast->NewState = ~0;
new_state = ~0;
}
if (new_state & swrast->InvalidateTriangleMask)
swrast->Triangle = _swrast_validate_triangle;
if (new_state & swrast->InvalidateLineMask)
swrast->Line = _swrast_validate_line;
if (new_state & swrast->InvalidatePointMask)
swrast->Point = _swrast_validate_point;
if (new_state & _SWRAST_NEW_BLEND_FUNC)
swrast->BlendFunc = _swrast_validate_blend_func;
if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC)
for (i = 0 ; i < ARRAY_SIZE(swrast->TextureSample); i++)
swrast->TextureSample[i] = NULL;
}
void
_swrast_update_texture_samplers(struct gl_context *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint u;
if (!swrast)
return; /* pipe hack */
for (u = 0; u < ARRAY_SIZE(swrast->TextureSample); u++) {
struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
/* Note: If tObj is NULL, the sample function will be a simple
* function that just returns opaque black (0,0,0,1).
*/
_mesa_update_fetch_functions(ctx, u);
swrast->TextureSample[u] =
_swrast_choose_texture_sample_func(ctx, tObj,
_mesa_get_samplerobj(ctx, u));
}
}
/**
* Update swrast->_ActiveAttribs, swrast->_NumActiveAttribs,
* swrast->_ActiveAtttribMask.
*/
static void
_swrast_update_active_attribs(struct gl_context *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLbitfield64 attribsMask;
/*
* Compute _ActiveAttribsMask = which fragment attributes are needed.
*/
if (_swrast_use_fragment_program(ctx)) {
/* fragment program/shader */
attribsMask = ctx->FragmentProgram._Current->info.inputs_read;
attribsMask &= ~VARYING_BIT_POS; /* WPOS is always handled specially */
}
else if (_mesa_ati_fragment_shader_enabled(ctx)) {
attribsMask = VARYING_BIT_COL0 | VARYING_BIT_COL1 |
VARYING_BIT_FOGC | VARYING_BITS_TEX_ANY;
}
else {
/* fixed function */
attribsMask = 0x0;
#if CHAN_TYPE == GL_FLOAT
attribsMask |= VARYING_BIT_COL0;
#endif
if (ctx->Fog.ColorSumEnabled ||
(ctx->Light.Enabled &&
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
attribsMask |= VARYING_BIT_COL1;
}
if (swrast->_FogEnabled)
attribsMask |= VARYING_BIT_FOGC;
attribsMask |= (ctx->Texture._EnabledCoordUnits << VARYING_SLOT_TEX0);
}
swrast->_ActiveAttribMask = attribsMask;
/* Update _ActiveAttribs[] list */
{
GLuint i, num = 0;
for (i = 0; i < VARYING_SLOT_MAX; i++) {
if (attribsMask & BITFIELD64_BIT(i)) {
swrast->_ActiveAttribs[num++] = i;
/* how should this attribute be interpolated? */
if (i == VARYING_SLOT_COL0 || i == VARYING_SLOT_COL1)
swrast->_InterpMode[i] = ctx->Light.ShadeModel;
else
swrast->_InterpMode[i] = GL_SMOOTH;
}
}
swrast->_NumActiveAttribs = num;
}
}
void
_swrast_validate_derived( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->NewState) {
if (swrast->NewState & _NEW_POLYGON)
_swrast_update_polygon( ctx );
if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM))
_swrast_update_fog_hint( ctx );
if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE)
_swrast_update_texture_env( ctx );
if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
_swrast_update_fog_state( ctx );
if (swrast->NewState & (_NEW_PROGRAM_CONSTANTS | _NEW_PROGRAM))
_swrast_update_fragment_program( ctx, swrast->NewState );
if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) {
_swrast_update_texture_samplers( ctx );
}
if (swrast->NewState & (_NEW_COLOR | _NEW_PROGRAM))
_swrast_update_deferred_texture(ctx);
if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
_swrast_update_rasterflags( ctx );
if (swrast->NewState & (_NEW_DEPTH |
_NEW_FOG |
_NEW_LIGHT |
_NEW_PROGRAM |
_NEW_TEXTURE))
_swrast_update_active_attribs(ctx);
if (swrast->NewState & (_NEW_FOG |
_NEW_PROGRAM |
_NEW_LIGHT |
_NEW_TEXTURE))
_swrast_update_specular_vertex_add(ctx);
swrast->NewState = 0;
swrast->StateChanges = 0;
swrast->InvalidateState = _swrast_invalidate_state;
}
}
#define SWRAST_DEBUG 0
/* Public entrypoints: See also s_bitmap.c, etc.
*/
void
_swrast_Quad( struct gl_context *ctx,
const SWvertex *v0, const SWvertex *v1,
const SWvertex *v2, const SWvertex *v3 )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_Quad\n");
_swrast_print_vertex( ctx, v0 );
_swrast_print_vertex( ctx, v1 );
_swrast_print_vertex( ctx, v2 );
_swrast_print_vertex( ctx, v3 );
}
SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 );
SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 );
}
void
_swrast_Triangle( struct gl_context *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2 )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_Triangle\n");
_swrast_print_vertex( ctx, v0 );
_swrast_print_vertex( ctx, v1 );
_swrast_print_vertex( ctx, v2 );
}
SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 );
}
void
_swrast_Line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_Line\n");
_swrast_print_vertex( ctx, v0 );
_swrast_print_vertex( ctx, v1 );
}
SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 );
}
void
_swrast_Point( struct gl_context *ctx, const SWvertex *v0 )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_Point\n");
_swrast_print_vertex( ctx, v0 );
}
SWRAST_CONTEXT(ctx)->Point( ctx, v0 );
}
void
_swrast_InvalidateState( struct gl_context *ctx, GLbitfield new_state )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_InvalidateState\n");
}
SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state );
}
void
_swrast_ResetLineStipple( struct gl_context *ctx )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_ResetLineStipple\n");
}
SWRAST_CONTEXT(ctx)->StippleCounter = 0;
}
void
_swrast_SetFacing(struct gl_context *ctx, GLuint facing)
{
SWRAST_CONTEXT(ctx)->PointLineFacing = facing;
}
void
_swrast_allow_vertex_fog( struct gl_context *ctx, GLboolean value )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value);
}
SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
SWRAST_CONTEXT(ctx)->AllowVertexFog = value;
}
void
_swrast_allow_pixel_fog( struct gl_context *ctx, GLboolean value )
{
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value);
}
SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
SWRAST_CONTEXT(ctx)->AllowPixelFog = value;
}
/**
* Initialize native program limits by copying the logical limits.
* See comments in init_program_limits() in context.c
*/
static void
init_program_native_limits(struct gl_program_constants *prog)
{
prog->MaxNativeInstructions = prog->MaxInstructions;
prog->MaxNativeAluInstructions = prog->MaxAluInstructions;
prog->MaxNativeTexInstructions = prog->MaxTexInstructions;
prog->MaxNativeTexIndirections = prog->MaxTexIndirections;
prog->MaxNativeAttribs = prog->MaxAttribs;
prog->MaxNativeTemps = prog->MaxTemps;
prog->MaxNativeAddressRegs = prog->MaxAddressRegs;
prog->MaxNativeParameters = prog->MaxParameters;
}
GLboolean
_swrast_CreateContext( struct gl_context *ctx )
{
GLuint i;
SWcontext *swrast = calloc(1, sizeof(SWcontext));
#ifdef _OPENMP
const GLuint maxThreads = omp_get_max_threads();
#else
const GLuint maxThreads = 1;
#endif
assert(ctx->Const.MaxViewportWidth <= SWRAST_MAX_WIDTH);
assert(ctx->Const.MaxViewportHeight <= SWRAST_MAX_WIDTH);
assert(ctx->Const.MaxRenderbufferSize <= SWRAST_MAX_WIDTH);
/* make sure largest texture image is <= SWRAST_MAX_WIDTH in size */
assert(ctx->Const.MaxTextureSize <= SWRAST_MAX_WIDTH);
assert((1 << (ctx->Const.MaxCubeTextureLevels - 1)) <= SWRAST_MAX_WIDTH);
assert((1 << (ctx->Const.Max3DTextureLevels - 1)) <= SWRAST_MAX_WIDTH);
assert(PROG_MAX_WIDTH == SWRAST_MAX_WIDTH);
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_CreateContext\n");
}
if (!swrast)
return GL_FALSE;
swrast->NewState = ~0;
swrast->choose_point = _swrast_choose_point;
swrast->choose_line = _swrast_choose_line;
swrast->choose_triangle = _swrast_choose_triangle;
swrast->InvalidatePointMask = _SWRAST_NEW_POINT;
swrast->InvalidateLineMask = _SWRAST_NEW_LINE;
swrast->InvalidateTriangleMask = _SWRAST_NEW_TRIANGLE;
swrast->Point = _swrast_validate_point;
swrast->Line = _swrast_validate_line;
swrast->Triangle = _swrast_validate_triangle;
swrast->InvalidateState = _swrast_sleep;
swrast->BlendFunc = _swrast_validate_blend_func;
swrast->AllowVertexFog = GL_TRUE;
swrast->AllowPixelFog = GL_TRUE;
swrast->Driver.SpanRenderStart = _swrast_span_render_start;
swrast->Driver.SpanRenderFinish = _swrast_span_render_finish;
for (i = 0; i < ARRAY_SIZE(swrast->TextureSample); i++)
swrast->TextureSample[i] = NULL;
/* SpanArrays is global and shared by all SWspan instances. However, when
* using multiple threads, it is necessary to have one SpanArrays instance
* per thread.
*/
swrast->SpanArrays = malloc(maxThreads * sizeof(SWspanarrays));
if (!swrast->SpanArrays) {
free(swrast);
return GL_FALSE;
}
for(i = 0; i < maxThreads; i++) {
swrast->SpanArrays[i].ChanType = CHAN_TYPE;
#if CHAN_TYPE == GL_UNSIGNED_BYTE
swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba8;
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba16;
#else
swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].attribs[VARYING_SLOT_COL0];
#endif
}
/* init point span buffer */
swrast->PointSpan.primitive = GL_POINT;
swrast->PointSpan.end = 0;
swrast->PointSpan.facing = 0;
swrast->PointSpan.array = swrast->SpanArrays;
init_program_native_limits(&ctx->Const.Program[MESA_SHADER_VERTEX]);
init_program_native_limits(&ctx->Const.Program[MESA_SHADER_GEOMETRY]);
init_program_native_limits(&ctx->Const.Program[MESA_SHADER_FRAGMENT]);
ctx->swrast_context = swrast;
swrast->stencil_temp.buf1 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
swrast->stencil_temp.buf2 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
swrast->stencil_temp.buf3 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
swrast->stencil_temp.buf4 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
if (!swrast->stencil_temp.buf1 ||
!swrast->stencil_temp.buf2 ||
!swrast->stencil_temp.buf3 ||
!swrast->stencil_temp.buf4) {
_swrast_DestroyContext(ctx);
return GL_FALSE;
}
return GL_TRUE;
}
void
_swrast_DestroyContext( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (SWRAST_DEBUG) {
_mesa_debug(ctx, "_swrast_DestroyContext\n");
}
free( swrast->SpanArrays );
free( swrast->ZoomedArrays );
free( swrast->TexelBuffer );
free(swrast->stencil_temp.buf1);
free(swrast->stencil_temp.buf2);
free(swrast->stencil_temp.buf3);
free(swrast->stencil_temp.buf4);
free( swrast );
ctx->swrast_context = 0;
}
struct swrast_device_driver *
_swrast_GetDeviceDriverReference( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
return &swrast->Driver;
}
void
_swrast_flush( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* flush any pending fragments from rendering points */
if (swrast->PointSpan.end > 0) {
_swrast_write_rgba_span(ctx, &(swrast->PointSpan));
swrast->PointSpan.end = 0;
}
}
void
_swrast_render_primitive( struct gl_context *ctx, GLenum prim )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) {
_swrast_flush(ctx);
}
swrast->Primitive = prim;
}
/** called via swrast->Driver.SpanRenderStart() */
void
_swrast_span_render_start(struct gl_context *ctx)
{
_swrast_map_textures(ctx);
_swrast_map_renderbuffers(ctx);
}
/** called via swrast->Driver.SpanRenderFinish() */
void
_swrast_span_render_finish(struct gl_context *ctx)
{
_swrast_unmap_textures(ctx);
_swrast_unmap_renderbuffers(ctx);
}
void
_swrast_render_start( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Driver.SpanRenderStart)
swrast->Driver.SpanRenderStart( ctx );
swrast->PointSpan.end = 0;
}
void
_swrast_render_finish( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_query_object *query = ctx->Query.CurrentOcclusionObject;
_swrast_flush(ctx);
if (swrast->Driver.SpanRenderFinish)
swrast->Driver.SpanRenderFinish( ctx );
if (query && (query->Target == GL_ANY_SAMPLES_PASSED ||
query->Target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE))
query->Result = !!query->Result;
}
#define SWRAST_DEBUG_VERTICES 0
void
_swrast_print_vertex( struct gl_context *ctx, const SWvertex *v )
{
GLuint i;
if (SWRAST_DEBUG_VERTICES) {
_mesa_debug(ctx, "win %f %f %f %f\n",
v->attrib[VARYING_SLOT_POS][0],
v->attrib[VARYING_SLOT_POS][1],
v->attrib[VARYING_SLOT_POS][2],
v->attrib[VARYING_SLOT_POS][3]);
for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
if (ctx->Texture.Unit[i]._Current)
_mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
v->attrib[VARYING_SLOT_TEX0 + i][0],
v->attrib[VARYING_SLOT_TEX0 + i][1],
v->attrib[VARYING_SLOT_TEX0 + i][2],
v->attrib[VARYING_SLOT_TEX0 + i][3]);
#if CHAN_TYPE == GL_FLOAT
_mesa_debug(ctx, "color %f %f %f %f\n",
v->color[0], v->color[1], v->color[2], v->color[3]);
#else
_mesa_debug(ctx, "color %d %d %d %d\n",
v->color[0], v->color[1], v->color[2], v->color[3]);
#endif
_mesa_debug(ctx, "spec %g %g %g %g\n",
v->attrib[VARYING_SLOT_COL1][0],
v->attrib[VARYING_SLOT_COL1][1],
v->attrib[VARYING_SLOT_COL1][2],
v->attrib[VARYING_SLOT_COL1][3]);
_mesa_debug(ctx, "fog %f\n", v->attrib[VARYING_SLOT_FOGC][0]);
_mesa_debug(ctx, "index %f\n", v->attrib[VARYING_SLOT_CI][0]);
_mesa_debug(ctx, "pointsize %f\n", v->pointSize);
_mesa_debug(ctx, "\n");
}
}

View File

@ -1,499 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file swrast/s_context.h
* \brief Software rasterization context and private types.
* \author Keith Whitwell <keithw@vmware.com>
*/
/**
* \mainpage swrast module
*
* This module, software rasterization, contains the software fallback
* routines for drawing points, lines, triangles, bitmaps and images.
* All rendering boils down to writing spans (arrays) of pixels with
* particular colors. The span-writing routines must be implemented
* by the device driver.
*/
#ifndef S_CONTEXT_H
#define S_CONTEXT_H
#include "main/mtypes.h"
#include "main/texcompress.h"
#include "program/prog_execute.h"
#include "swrast.h"
#include "s_fragprog.h"
#include "s_span.h"
#include "util/rounding.h"
typedef void (*texture_sample_func)(struct gl_context *ctx,
const struct gl_sampler_object *samp,
const struct gl_texture_object *tObj,
GLuint n, const GLfloat texcoords[][4],
const GLfloat lambda[], GLfloat rgba[][4]);
typedef void (*swrast_blend_func)(struct gl_context *ctx, GLuint n,
const GLubyte mask[],
GLvoid *src, const GLvoid *dst,
GLenum chanType);
typedef void (*swrast_point_func)( struct gl_context *ctx, const SWvertex *);
typedef void (*swrast_line_func)( struct gl_context *ctx,
const SWvertex *, const SWvertex *);
typedef void (*swrast_tri_func)( struct gl_context *ctx, const SWvertex *,
const SWvertex *, const SWvertex *);
typedef void (*validate_texture_image_func)(struct gl_context *ctx,
struct gl_texture_object *texObj,
GLuint face, GLuint level);
/**
* \defgroup Bitmasks
* Bitmasks to indicate which rasterization options are enabled
* (RasterMask)
*/
/*@{*/
#define ALPHATEST_BIT 0x001 /**< Alpha-test pixels */
#define BLEND_BIT 0x002 /**< Blend pixels */
#define DEPTH_BIT 0x004 /**< Depth-test pixels */
#define FOG_BIT 0x008 /**< Fog pixels */
#define LOGIC_OP_BIT 0x010 /**< Apply logic op in software */
#define CLIP_BIT 0x020 /**< Scissor or window clip pixels */
#define STENCIL_BIT 0x040 /**< Stencil pixels */
#define MASKING_BIT 0x080 /**< Do glColorMask or glIndexMask */
#define MULTI_DRAW_BIT 0x400 /**< Write to more than one color- */
/**< buffer or no buffers. */
#define OCCLUSION_BIT 0x800 /**< GL_HP_occlusion_test enabled */
#define TEXTURE_BIT 0x1000 /**< Texturing really enabled */
#define FRAGPROG_BIT 0x2000 /**< Fragment program enabled */
#define ATIFRAGSHADER_BIT 0x4000 /**< ATI Fragment shader enabled */
#define CLAMPING_BIT 0x8000 /**< Clamp colors to [0,1] */
/*@}*/
#define _SWRAST_NEW_RASTERMASK (_NEW_BUFFERS| \
_NEW_SCISSOR| \
_NEW_COLOR| \
_NEW_DEPTH| \
_NEW_FOG| \
_NEW_PROGRAM| \
_NEW_STENCIL| \
_NEW_TEXTURE| \
_NEW_VIEWPORT| \
_NEW_DEPTH)
struct swrast_texture_image;
/**
* Fetch a texel from texture image at given position.
*/
typedef void (*FetchTexelFunc)(const struct swrast_texture_image *texImage,
GLint col, GLint row, GLint img,
GLfloat *texelOut);
/**
* Subclass of gl_texture_image.
* We need extra fields/info to keep tracking of mapped texture buffers,
* strides and Fetch functions.
*/
struct swrast_texture_image
{
struct gl_texture_image Base;
GLboolean _IsPowerOfTwo; /**< Are all dimensions powers of two? */
/** used for mipmap LOD computation */
GLfloat WidthScale, HeightScale, DepthScale;
/**
* Byte stride between rows in ImageSlices.
*
* For compressed textures, this is the byte stride between one row of
* blocks and the next row of blocks.
*
* Only valid while one of the ImageSlices is mapped, and must be the same
* between all slices.
*/
GLint RowStride;
/**
* When a texture image is mapped for swrast, this array contains pointers
* to the beginning of each slice.
*
* For swrast-allocated textures, these pointers will always stay
* initialized to point within Buffer.
*/
void **ImageSlices;
/** Malloc'd texture memory */
GLubyte *Buffer;
FetchTexelFunc FetchTexel;
/** For fetching texels from compressed textures */
compressed_fetch_func FetchCompressedTexel;
};
/** cast wrapper */
static inline struct swrast_texture_image *
swrast_texture_image(struct gl_texture_image *img)
{
return (struct swrast_texture_image *) img;
}
/** cast wrapper */
static inline const struct swrast_texture_image *
swrast_texture_image_const(const struct gl_texture_image *img)
{
return (const struct swrast_texture_image *) img;
}
/**
* Subclass of gl_renderbuffer with extra fields needed for software
* rendering.
*/
struct swrast_renderbuffer
{
struct gl_renderbuffer Base;
GLubyte *Buffer; /**< The malloc'd memory for buffer */
/** These fields are only valid while buffer is mapped for rendering */
GLubyte *Map;
GLint RowStride; /**< in bytes */
/** For span rendering */
GLenum ColorType;
};
/** cast wrapper */
static inline struct swrast_renderbuffer *
swrast_renderbuffer(struct gl_renderbuffer *img)
{
return (struct swrast_renderbuffer *) img;
}
/**
* \struct SWcontext
* \brief Per-context state that's private to the software rasterizer module.
*/
typedef struct
{
/** Driver interface:
*/
struct swrast_device_driver Driver;
/** Configuration mechanisms to make software rasterizer match
* characteristics of the hardware rasterizer (if present):
*/
GLboolean AllowVertexFog;
GLboolean AllowPixelFog;
/** Derived values, invalidated on statechanges, updated from
* _swrast_validate_derived():
*/
GLbitfield _RasterMask;
GLfloat _BackfaceSign; /** +1 or -1 */
GLfloat _BackfaceCullSign; /** +1, 0, or -1 */
GLboolean _PreferPixelFog; /* Compute fog blend factor per fragment? */
GLboolean _TextureCombinePrimary;
GLboolean _FogEnabled;
GLboolean _DeferredTexture;
/** List/array of the fragment attributes to interpolate */
GLuint _ActiveAttribs[VARYING_SLOT_MAX];
/** Same info, but as a bitmask of VARYING_BIT_x bits */
GLbitfield64 _ActiveAttribMask;
/** Number of fragment attributes to interpolate */
GLuint _NumActiveAttribs;
/** Indicates how each attrib is to be interpolated (lines/tris) */
GLenum _InterpMode[VARYING_SLOT_MAX]; /* GL_FLAT or GL_SMOOTH (for now) */
/* Working values:
*/
GLuint StippleCounter; /**< Line stipple counter */
GLuint PointLineFacing;
GLbitfield NewState;
GLuint StateChanges;
GLenum Primitive; /* current primitive being drawn (ala glBegin) */
GLboolean SpecularVertexAdd; /**< Add specular/secondary color per vertex */
void (*InvalidateState)( struct gl_context *ctx, GLbitfield new_state );
/**
* When the NewState mask intersects these masks, we invalidate the
* Point/Line/Triangle function pointers below.
*/
/*@{*/
GLbitfield InvalidatePointMask;
GLbitfield InvalidateLineMask;
GLbitfield InvalidateTriangleMask;
/*@}*/
/**
* Device drivers plug in functions for these callbacks.
* Will be called when the GL state change mask intersects the above masks.
*/
/*@{*/
void (*choose_point)( struct gl_context * );
void (*choose_line)( struct gl_context * );
void (*choose_triangle)( struct gl_context * );
/*@}*/
/**
* Current point, line and triangle drawing functions.
*/
/*@{*/
swrast_point_func Point;
swrast_line_func Line;
swrast_tri_func Triangle;
/*@}*/
/**
* Placeholders for when separate specular (or secondary color) is
* enabled but texturing is not.
*/
/*@{*/
swrast_point_func SpecPoint;
swrast_line_func SpecLine;
swrast_tri_func SpecTriangle;
/*@}*/
/**
* Typically, we'll allocate a sw_span structure as a local variable
* and set its 'array' pointer to point to this object. The reason is
* this object is big and causes problems when allocated on the stack
* on some systems.
*/
SWspanarrays *SpanArrays;
SWspanarrays *ZoomedArrays; /**< For pixel zooming */
/**
* Used to buffer N GL_POINTS, instead of rendering one by one.
*/
SWspan PointSpan;
/** Internal hooks, kept up to date by the same mechanism as above.
*/
swrast_blend_func BlendFunc;
texture_sample_func TextureSample[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
/** Buffer for saving the sampled texture colors.
* Needed for GL_ARB_texture_env_crossbar implementation.
*/
GLfloat *TexelBuffer;
validate_texture_image_func ValidateTextureImage;
/** State used during execution of fragment programs */
struct gl_program_machine FragProgMachine;
/** Temporary arrays for stencil operations. To avoid large stack
* allocations.
*/
struct {
GLubyte *buf1, *buf2, *buf3, *buf4;
} stencil_temp;
} SWcontext;
extern void
_swrast_validate_derived( struct gl_context *ctx );
extern void
_swrast_update_texture_samplers(struct gl_context *ctx);
/** Return SWcontext for the given struct gl_context */
static inline SWcontext *
SWRAST_CONTEXT(struct gl_context *ctx)
{
return (SWcontext *) ctx->swrast_context;
}
/** const version of above */
static inline const SWcontext *
CONST_SWRAST_CONTEXT(const struct gl_context *ctx)
{
return (const SWcontext *) ctx->swrast_context;
}
/**
* Called prior to framebuffer reading/writing.
* For drivers that rely on swrast for fallback rendering, this is the
* driver's opportunity to map renderbuffers and textures.
*/
static inline void
swrast_render_start(struct gl_context *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Driver.SpanRenderStart)
swrast->Driver.SpanRenderStart(ctx);
}
/** Called after framebuffer reading/writing */
static inline void
swrast_render_finish(struct gl_context *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Driver.SpanRenderFinish)
swrast->Driver.SpanRenderFinish(ctx);
}
extern void
_swrast_span_render_start(struct gl_context *ctx);
extern void
_swrast_span_render_finish(struct gl_context *ctx);
extern void
_swrast_map_textures(struct gl_context *ctx);
extern void
_swrast_unmap_textures(struct gl_context *ctx);
extern unsigned int
_swrast_teximage_slice_height(struct gl_texture_image *texImage);
extern void
_swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj);
extern void
_swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj);
extern void
_swrast_map_renderbuffers(struct gl_context *ctx);
extern void
_swrast_unmap_renderbuffers(struct gl_context *ctx);
/**
* Size of an RGBA pixel, in bytes, for given datatype.
*/
#define RGBA_PIXEL_SIZE(TYPE) \
((TYPE == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) : \
((TYPE == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort) \
: 4 * sizeof(GLfloat)))
/*
* Fixed point arithmetic macros
*/
#ifndef FIXED_FRAC_BITS
#define FIXED_FRAC_BITS 11
#endif
#define FIXED_SHIFT FIXED_FRAC_BITS
#define FIXED_ONE (1 << FIXED_SHIFT)
#define FIXED_HALF (1 << (FIXED_SHIFT-1))
#define FIXED_FRAC_MASK (FIXED_ONE - 1)
#define FIXED_INT_MASK (~FIXED_FRAC_MASK)
#define FIXED_EPSILON 1
#define FIXED_SCALE ((float) FIXED_ONE)
#define FIXED_DBL_SCALE ((double) FIXED_ONE)
#define FloatToFixed(X) (lroundf((X) * FIXED_SCALE))
#define FixedToDouble(X) ((X) * (1.0 / FIXED_DBL_SCALE))
#define IntToFixed(I) ((I) << FIXED_SHIFT)
#define FixedToInt(X) ((X) >> FIXED_SHIFT)
#define FixedToUns(X) (((unsigned int)(X)) >> FIXED_SHIFT)
#define FixedCeil(X) (((X) + FIXED_ONE - FIXED_EPSILON) & FIXED_INT_MASK)
#define FixedFloor(X) ((X) & FIXED_INT_MASK)
#define FixedToFloat(X) ((X) * (1.0F / FIXED_SCALE))
#define PosFloatToFixed(X) FloatToFixed(X)
#define SignedFloatToFixed(X) FloatToFixed(X)
/*
* XXX these macros are just bandages for now in order to make
* CHAN_BITS==32 compile cleanly.
* These should probably go elsewhere at some point.
*/
#if CHAN_TYPE == GL_FLOAT
#define ChanToFixed(X) (X)
#define FixedToChan(X) (X)
#else
#define ChanToFixed(X) IntToFixed(X)
#define FixedToChan(X) FixedToInt(X)
#endif
/**
* For looping over fragment attributes in the pointe, line
* triangle rasterizers.
*/
#define ATTRIB_LOOP_BEGIN \
{ \
GLuint a; \
for (a = 0; a < swrast->_NumActiveAttribs; a++) { \
const GLuint attr = swrast->_ActiveAttribs[a];
#define ATTRIB_LOOP_END } }
/**
* Return the address of a pixel value in a mapped renderbuffer.
*/
static inline GLubyte *
_swrast_pixel_address(struct gl_renderbuffer *rb, GLint x, GLint y)
{
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
const GLint bpp = _mesa_get_format_bytes(rb->Format);
const GLint rowStride = srb->RowStride;
assert(x >= 0);
assert(y >= 0);
/* NOTE: using <= only because of s_tritemp.h which gets a pixel
* address but doesn't necessarily access it.
*/
assert(x <= (GLint) rb->Width);
assert(y <= (GLint) rb->Height);
assert(srb->Map);
return (GLubyte *) srb->Map + y * rowStride + x * bpp;
}
#endif

View File

@ -1,668 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/condrender.h"
#include "main/macros.h"
#include "main/blit.h"
#include "main/pixeltransfer.h"
#include "s_context.h"
#include "s_depth.h"
#include "s_span.h"
#include "s_stencil.h"
#include "s_zoom.h"
/**
* Determine if there's overlap in an image copy.
* This test also compensates for the fact that copies are done from
* bottom to top and overlaps can sometimes be handled correctly
* without making a temporary image copy.
* \return GL_TRUE if the regions overlap, GL_FALSE otherwise.
*/
static GLboolean
regions_overlap(GLint srcx, GLint srcy,
GLint dstx, GLint dsty,
GLint width, GLint height,
GLfloat zoomX, GLfloat zoomY)
{
if (zoomX == 1.0F && zoomY == 1.0F) {
return _mesa_regions_overlap(srcx, srcy, srcx + width, srcy + height,
dstx, dsty, dstx + width, dsty + height);
}
else {
/* add one pixel of slop when zooming, just to be safe */
if (srcx > (dstx + ((zoomX > 0.0F) ? (width * zoomX + 1.0F) : 0.0F))) {
/* src is completely right of dest */
return GL_FALSE;
}
else if (srcx + width + 1.0F < dstx + ((zoomX > 0.0F) ? 0.0F : (width * zoomX))) {
/* src is completely left of dest */
return GL_FALSE;
}
else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
/* src is completely below dest */
return GL_FALSE;
}
else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
/* src is completely above dest */
return GL_FALSE;
}
else {
return GL_TRUE;
}
}
}
/**
* RGBA copypixels
*/
static void
copy_rgba_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
GLint width, GLint height, GLint destx, GLint desty)
{
GLfloat *tmpImage, *p;
GLint sy, dy, stepy, row;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
GLint overlapping;
GLuint transferOps = ctx->_ImageTransferState;
SWspan span;
if (!ctx->ReadBuffer->_ColorReadBuffer) {
/* no readbuffer - OK */
return;
}
if (ctx->DrawBuffer == ctx->ReadBuffer) {
overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
}
else {
overlapping = GL_FALSE;
}
/* Determine if copy should be done bottom-to-top or top-to-bottom */
if (!overlapping && srcy < desty) {
/* top-down max-to-min */
sy = srcy + height - 1;
dy = desty + height - 1;
stepy = -1;
}
else {
/* bottom-up min-to-max */
sy = srcy;
dy = desty;
stepy = 1;
}
INIT_SPAN(span, GL_BITMAP);
_swrast_span_default_attribs(ctx, &span);
span.arrayMask = SPAN_RGBA;
span.arrayAttribs = VARYING_BIT_COL0; /* we'll fill in COL0 attrib values */
if (overlapping) {
tmpImage = malloc(width * height * sizeof(GLfloat) * 4);
if (!tmpImage) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
return;
}
/* read the source image as RGBA/float */
p = tmpImage;
for (row = 0; row < height; row++) {
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, srcx, sy + row, p );
p += width * 4;
}
p = tmpImage;
}
else {
tmpImage = NULL; /* silence compiler warnings */
p = NULL;
}
assert(width < SWRAST_MAX_WIDTH);
for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
GLvoid *rgba = span.array->attribs[VARYING_SLOT_COL0];
/* Get row/span of source pixels */
if (overlapping) {
/* get from buffered image */
memcpy(rgba, p, width * sizeof(GLfloat) * 4);
p += width * 4;
}
else {
/* get from framebuffer */
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, srcx, sy, rgba );
}
if (transferOps) {
_mesa_apply_rgba_transfer_ops(ctx, transferOps, width,
(GLfloat (*)[4]) rgba);
}
/* Write color span */
span.x = destx;
span.y = dy;
span.end = width;
span.array->ChanType = GL_FLOAT;
if (zoom) {
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
}
else {
_swrast_write_rgba_span(ctx, &span);
}
}
span.array->ChanType = CHAN_TYPE; /* restore */
if (overlapping)
free(tmpImage);
}
/**
* Convert floating point Z values to integer Z values with pixel transfer's
* Z scale and bias.
*/
static void
scale_and_bias_z(struct gl_context *ctx, GLuint width,
const GLfloat depth[], GLuint z[])
{
const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
GLuint i;
if (depthMax <= 0xffffff &&
ctx->Pixel.DepthScale == 1.0F &&
ctx->Pixel.DepthBias == 0.0F) {
/* no scale or bias and no clamping and no worry of overflow */
const GLfloat depthMaxF = ctx->DrawBuffer->_DepthMaxF;
for (i = 0; i < width; i++) {
z[i] = (GLuint) (depth[i] * depthMaxF);
}
}
else {
/* need to be careful with overflow */
const GLdouble depthMaxF = ctx->DrawBuffer->_DepthMaxF;
for (i = 0; i < width; i++) {
GLdouble d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
d = SATURATE(d) * depthMaxF;
if (d >= depthMaxF)
z[i] = depthMax;
else
z[i] = (GLuint) d;
}
}
}
/*
* TODO: Optimize!!!!
*/
static void
copy_depth_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
GLint width, GLint height,
GLint destx, GLint desty )
{
struct gl_framebuffer *fb = ctx->ReadBuffer;
struct gl_renderbuffer *readRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
GLfloat *p, *tmpImage, *depth;
GLint sy, dy, stepy;
GLint j;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
GLint overlapping;
SWspan span;
if (!readRb) {
/* no readbuffer - OK */
return;
}
INIT_SPAN(span, GL_BITMAP);
_swrast_span_default_attribs(ctx, &span);
span.arrayMask = SPAN_Z;
if (ctx->DrawBuffer == ctx->ReadBuffer) {
overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
}
else {
overlapping = GL_FALSE;
}
/* Determine if copy should be bottom-to-top or top-to-bottom */
if (!overlapping && srcy < desty) {
/* top-down max-to-min */
sy = srcy + height - 1;
dy = desty + height - 1;
stepy = -1;
}
else {
/* bottom-up min-to-max */
sy = srcy;
dy = desty;
stepy = 1;
}
if (overlapping) {
GLint ssy = sy;
tmpImage = malloc(width * height * sizeof(GLfloat));
if (!tmpImage) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
return;
}
p = tmpImage;
for (j = 0; j < height; j++, ssy += stepy) {
_swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p);
p += width;
}
p = tmpImage;
}
else {
tmpImage = NULL; /* silence compiler warning */
p = NULL;
}
depth = malloc(width * sizeof(GLfloat));
if (!depth) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels()");
goto end;
}
for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
/* get depth values */
if (overlapping) {
memcpy(depth, p, width * sizeof(GLfloat));
p += width;
}
else {
_swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth);
}
/* apply scale and bias */
scale_and_bias_z(ctx, width, depth, span.array->z);
/* write depth values */
span.x = destx;
span.y = dy;
span.end = width;
if (zoom)
_swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
else
_swrast_write_rgba_span(ctx, &span);
}
free(depth);
end:
if (overlapping)
free(tmpImage);
}
static void
copy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
GLint width, GLint height,
GLint destx, GLint desty )
{
struct gl_framebuffer *fb = ctx->ReadBuffer;
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
GLint sy, dy, stepy;
GLint j;
GLubyte *p, *tmpImage, *stencil;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
GLint overlapping;
if (!rb) {
/* no readbuffer - OK */
return;
}
if (ctx->DrawBuffer == ctx->ReadBuffer) {
overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
}
else {
overlapping = GL_FALSE;
}
/* Determine if copy should be bottom-to-top or top-to-bottom */
if (!overlapping && srcy < desty) {
/* top-down max-to-min */
sy = srcy + height - 1;
dy = desty + height - 1;
stepy = -1;
}
else {
/* bottom-up min-to-max */
sy = srcy;
dy = desty;
stepy = 1;
}
if (overlapping) {
GLint ssy = sy;
tmpImage = malloc(width * height * sizeof(GLubyte));
if (!tmpImage) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
return;
}
p = tmpImage;
for (j = 0; j < height; j++, ssy += stepy) {
_swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
p += width;
}
p = tmpImage;
}
else {
tmpImage = NULL; /* silence compiler warning */
p = NULL;
}
stencil = malloc(width * sizeof(GLubyte));
if (!stencil) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels()");
goto end;
}
for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
/* Get stencil values */
if (overlapping) {
memcpy(stencil, p, width * sizeof(GLubyte));
p += width;
}
else {
_swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
}
_mesa_apply_stencil_transfer_ops(ctx, width, stencil);
/* Write stencil values */
if (zoom) {
_swrast_write_zoomed_stencil_span(ctx, destx, desty, width,
destx, dy, stencil);
}
else {
_swrast_write_stencil_span( ctx, width, destx, dy, stencil );
}
}
free(stencil);
end:
if (overlapping)
free(tmpImage);
}
/**
* Try to do a fast 1:1 blit with memcpy.
* \return GL_TRUE if successful, GL_FALSE otherwise.
*/
GLboolean
swrast_fast_copy_pixels(struct gl_context *ctx,
struct gl_framebuffer *srcFb,
struct gl_framebuffer *dstFb,
GLint srcX, GLint srcY, GLsizei width, GLsizei height,
GLint dstX, GLint dstY, GLenum type)
{
struct gl_renderbuffer *srcRb, *dstRb;
GLint row;
GLuint pixelBytes, widthInBytes;
GLubyte *srcMap, *dstMap;
GLint srcRowStride, dstRowStride;
if (type == GL_COLOR) {
if (dstFb->_NumColorDrawBuffers != 1)
return GL_FALSE;
srcRb = srcFb->_ColorReadBuffer;
dstRb = dstFb->_ColorDrawBuffers[0];
}
else if (type == GL_STENCIL) {
srcRb = srcFb->Attachment[BUFFER_STENCIL].Renderbuffer;
dstRb = dstFb->Attachment[BUFFER_STENCIL].Renderbuffer;
}
else if (type == GL_DEPTH) {
srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
}
else {
assert(type == GL_DEPTH_STENCIL_EXT);
/* XXX correct? */
srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
}
/* src and dst renderbuffers must be same format */
if (!srcRb || !dstRb || srcRb->Format != dstRb->Format) {
return GL_FALSE;
}
if (type == GL_STENCIL || type == GL_DEPTH_COMPONENT) {
/* can't handle packed depth+stencil here */
if (_mesa_is_format_packed_depth_stencil(srcRb->Format) ||
_mesa_is_format_packed_depth_stencil(dstRb->Format))
return GL_FALSE;
}
else if (type == GL_DEPTH_STENCIL) {
/* can't handle separate depth/stencil buffers */
if (srcRb != srcFb->Attachment[BUFFER_STENCIL].Renderbuffer ||
dstRb != dstFb->Attachment[BUFFER_STENCIL].Renderbuffer)
return GL_FALSE;
}
/* clipping not supported */
if (srcX < 0 || srcX + width > (GLint) srcFb->Width ||
srcY < 0 || srcY + height > (GLint) srcFb->Height ||
dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
return GL_FALSE;
}
pixelBytes = _mesa_get_format_bytes(srcRb->Format);
widthInBytes = width * pixelBytes;
if (srcRb == dstRb) {
/* map whole buffer for read/write */
/* XXX we could be clever and just map the union region of the
* source and dest rects.
*/
GLubyte *map;
GLint rowStride;
ctx->Driver.MapRenderbuffer(ctx, srcRb, 0, 0,
srcRb->Width, srcRb->Height,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
&map, &rowStride, srcFb->FlipY);
if (!map) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
return GL_TRUE; /* don't retry with slow path */
}
srcMap = map + srcY * rowStride + srcX * pixelBytes;
dstMap = map + dstY * rowStride + dstX * pixelBytes;
/* this handles overlapping copies */
if (srcY < dstY) {
/* copy in reverse (top->down) order */
srcMap += rowStride * (height - 1);
dstMap += rowStride * (height - 1);
srcRowStride = -rowStride;
dstRowStride = -rowStride;
}
else {
/* copy in normal (bottom->up) order */
srcRowStride = rowStride;
dstRowStride = rowStride;
}
}
else {
/* different src/dst buffers */
ctx->Driver.MapRenderbuffer(ctx, srcRb, srcX, srcY,
width, height,
GL_MAP_READ_BIT, &srcMap, &srcRowStride,
srcFb->FlipY);
if (!srcMap) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
return GL_TRUE; /* don't retry with slow path */
}
ctx->Driver.MapRenderbuffer(ctx, dstRb, dstX, dstY,
width, height,
GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
dstFb->FlipY);
if (!dstMap) {
ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
return GL_TRUE; /* don't retry with slow path */
}
}
for (row = 0; row < height; row++) {
/* memmove() in case of overlap */
memmove(dstMap, srcMap, widthInBytes);
dstMap += dstRowStride;
srcMap += srcRowStride;
}
ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
if (dstRb != srcRb) {
ctx->Driver.UnmapRenderbuffer(ctx, dstRb);
}
return GL_TRUE;
}
/**
* Find/map the renderbuffer that we'll be reading from.
* The swrast_render_start() function only maps the drawing buffers,
* not the read buffer.
*/
static struct gl_renderbuffer *
map_readbuffer(struct gl_context *ctx, GLenum type)
{
struct gl_framebuffer *fb = ctx->ReadBuffer;
struct gl_renderbuffer *rb;
struct swrast_renderbuffer *srb;
switch (type) {
case GL_COLOR:
rb = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer;
break;
case GL_DEPTH:
case GL_DEPTH_STENCIL:
rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
break;
case GL_STENCIL:
rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
break;
default:
return NULL;
}
srb = swrast_renderbuffer(rb);
if (!srb || srb->Map) {
/* no buffer, or buffer is mapped already, we're done */
return NULL;
}
ctx->Driver.MapRenderbuffer(ctx, rb,
0, 0, rb->Width, rb->Height,
GL_MAP_READ_BIT,
&srb->Map, &srb->RowStride,
fb->FlipY);
return rb;
}
/**
* Do software-based glCopyPixels.
* By time we get here, all parameters will have been error-checked.
*/
void
_swrast_CopyPixels(struct gl_context *ctx,
GLint srcx, GLint srcy, GLsizei width, GLsizei height,
GLint destx, GLint desty, GLenum type)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_renderbuffer *rb;
if (!_mesa_check_conditional_render(ctx))
return; /* don't copy */
if (swrast->NewState)
_swrast_validate_derived( ctx );
if (!(SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != 1.0F ||
ctx->_ImageTransferState) &&
swrast_fast_copy_pixels(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
srcx, srcy, width, height, destx, desty,
type)) {
/* all done */
return;
}
swrast_render_start(ctx);
rb = map_readbuffer(ctx, type);
switch (type) {
case GL_COLOR:
copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
break;
case GL_DEPTH:
copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
break;
case GL_STENCIL:
copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
break;
case GL_DEPTH_STENCIL_EXT:
/* Copy buffers separately (if the fast copy path wasn't taken) */
copy_depth_pixels(ctx, srcx, srcy, width, height, destx, desty);
copy_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty);
break;
default:
_mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
}
swrast_render_finish(ctx);
if (rb) {
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
ctx->Driver.UnmapRenderbuffer(ctx, rb);
srb->Map = NULL;
}
}

View File

@ -1,854 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/formats.h"
#include "main/format_unpack.h"
#include "main/format_pack.h"
#include "main/macros.h"
#include "s_context.h"
#include "s_depth.h"
#include "s_span.h"
#define Z_TEST(COMPARE) \
do { \
GLuint i; \
for (i = 0; i < n; i++) { \
if (mask[i]) { \
if (COMPARE) { \
/* pass */ \
if (write) { \
zbuffer[i] = zfrag[i]; \
} \
passed++; \
} \
else { \
/* fail */ \
mask[i] = 0; \
} \
} \
} \
} while (0)
/**
* Do depth test for an array of 16-bit Z values.
* @param zbuffer array of Z buffer values (16-bit)
* @param zfrag array of fragment Z values (use 16-bit in 32-bit uint)
* @param mask which fragments are alive, killed afterward
* @return number of fragments which pass the test.
*/
static GLuint
depth_test_span16( struct gl_context *ctx, GLuint n,
GLushort zbuffer[], const GLuint zfrag[], GLubyte mask[] )
{
const GLboolean write = ctx->Depth.Mask;
GLuint passed = 0;
/* switch cases ordered from most frequent to less frequent */
switch (ctx->Depth.Func) {
case GL_LESS:
Z_TEST(zfrag[i] < zbuffer[i]);
break;
case GL_LEQUAL:
Z_TEST(zfrag[i] <= zbuffer[i]);
break;
case GL_GEQUAL:
Z_TEST(zfrag[i] >= zbuffer[i]);
break;
case GL_GREATER:
Z_TEST(zfrag[i] > zbuffer[i]);
break;
case GL_NOTEQUAL:
Z_TEST(zfrag[i] != zbuffer[i]);
break;
case GL_EQUAL:
Z_TEST(zfrag[i] == zbuffer[i]);
break;
case GL_ALWAYS:
Z_TEST(1);
break;
case GL_NEVER:
memset(mask, 0, n * sizeof(GLubyte));
break;
default:
_mesa_problem(ctx, "Bad depth func in depth_test_span16");
}
return passed;
}
/**
* Do depth test for an array of 32-bit Z values.
* @param zbuffer array of Z buffer values (32-bit)
* @param zfrag array of fragment Z values (use 32-bits in 32-bit uint)
* @param mask which fragments are alive, killed afterward
* @return number of fragments which pass the test.
*/
static GLuint
depth_test_span32( struct gl_context *ctx, GLuint n,
GLuint zbuffer[], const GLuint zfrag[], GLubyte mask[])
{
const GLboolean write = ctx->Depth.Mask;
GLuint passed = 0;
/* switch cases ordered from most frequent to less frequent */
switch (ctx->Depth.Func) {
case GL_LESS:
Z_TEST(zfrag[i] < zbuffer[i]);
break;
case GL_LEQUAL:
Z_TEST(zfrag[i] <= zbuffer[i]);
break;
case GL_GEQUAL:
Z_TEST(zfrag[i] >= zbuffer[i]);
break;
case GL_GREATER:
Z_TEST(zfrag[i] > zbuffer[i]);
break;
case GL_NOTEQUAL:
Z_TEST(zfrag[i] != zbuffer[i]);
break;
case GL_EQUAL:
Z_TEST(zfrag[i] == zbuffer[i]);
break;
case GL_ALWAYS:
Z_TEST(1);
break;
case GL_NEVER:
memset(mask, 0, n * sizeof(GLubyte));
break;
default:
_mesa_problem(ctx, "Bad depth func in depth_test_span32");
}
return passed;
}
/**
* Clamp fragment Z values to the depth near/far range (glDepthRange()).
* This is used when GL_ARB_depth_clamp/GL_DEPTH_CLAMP is turned on.
* In that case, vertexes are not clipped against the near/far planes
* so rasterization will produce fragment Z values outside the usual
* [0,1] range.
*/
void
_swrast_depth_clamp_span( struct gl_context *ctx, SWspan *span )
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
const GLuint count = span->end;
GLint *zValues = (GLint *) span->array->z; /* sign change */
GLint min, max;
GLfloat min_f, max_f;
GLuint i;
if (ctx->ViewportArray[0].Near < ctx->ViewportArray[0].Far) {
min_f = ctx->ViewportArray[0].Near;
max_f = ctx->ViewportArray[0].Far;
} else {
min_f = ctx->ViewportArray[0].Far;
max_f = ctx->ViewportArray[0].Near;
}
/* Convert floating point values in [0,1] to device Z coordinates in
* [0, DepthMax].
* ex: If the Z buffer has 24 bits, DepthMax = 0xffffff.
*
* XXX this all falls apart if we have 31 or more bits of Z because
* the triangle rasterization code produces unsigned Z values. Negative
* vertex Z values come out as large fragment Z uints.
*/
min = (GLint) (min_f * fb->_DepthMaxF);
max = (GLint) (max_f * fb->_DepthMaxF);
if (max < 0)
max = 0x7fffffff; /* catch over flow for 30-bit z */
/* Note that we do the comparisons here using signed integers.
*/
for (i = 0; i < count; i++) {
if (zValues[i] < min)
zValues[i] = min;
if (zValues[i] > max)
zValues[i] = max;
}
}
/**
* Get array of 32-bit z values from the depth buffer. With clipping.
* Note: the returned values are always in the range [0, 2^32-1].
*/
static void
get_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLuint count, const GLint x[], const GLint y[],
GLuint zbuffer[])
{
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
const GLint w = rb->Width, h = rb->Height;
const GLubyte *map = _swrast_pixel_address(rb, 0, 0);
GLuint i;
if (rb->Format == MESA_FORMAT_Z_UNORM32) {
const GLint rowStride = srb->RowStride;
for (i = 0; i < count; i++) {
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
zbuffer[i] = *((GLuint *) (map + y[i] * rowStride + x[i] * 4));
}
}
}
else {
const GLint bpp = _mesa_get_format_bytes(rb->Format);
const GLint rowStride = srb->RowStride;
for (i = 0; i < count; i++) {
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
const GLubyte *src = map + y[i] * rowStride+ x[i] * bpp;
_mesa_unpack_uint_z_row(rb->Format, 1, src, &zbuffer[i]);
}
}
}
}
/** Helper struct for MESA_FORMAT_Z32_FLOAT_S8X24_UINT */
struct z32f_x24s8
{
float z;
uint32_t x24s8;
};
/**
** Pack uint Z pixels. The incoming src value is always in
** the range [0, 2^32-1].
**/
static void
pack_uint_S8_UINT_Z24_UNORM(const uint32_t *src, void *dst)
{
/* don't disturb the stencil values */
uint32_t *d = ((uint32_t *) dst);
uint32_t s = *d & 0xff;
uint32_t z = *src & 0xffffff00;
*d = z | s;
}
static void
pack_uint_Z24_UNORM_S8_UINT(const uint32_t *src, void *dst)
{
/* don't disturb the stencil values */
uint32_t *d = ((uint32_t *) dst);
uint32_t s = *d & 0xff000000;
uint32_t z = *src >> 8;
*d = s | z;
}
static void
pack_uint_Z_UNORM16(const uint32_t *src, void *dst)
{
uint16_t *d = ((uint16_t *) dst);
*d = *src >> 16;
}
static void
pack_uint_Z_UNORM32(const uint32_t *src, void *dst)
{
uint32_t *d = ((uint32_t *) dst);
*d = *src;
}
/**
** Pack uint to Z_FLOAT32 or Z_FLOAT32_X24S8.
**/
static void
pack_uint_Z_FLOAT32(const uint32_t *src, void *dst)
{
float *d = ((float *) dst);
const double scale = 1.0 / (double) 0xffffffff;
*d = (float) (*src * scale);
assert(*d >= 0.0f);
assert(*d <= 1.0f);
}
/** Pack a uint32_t Z value to dest address */
typedef void (*mesa_pack_uint_z_func)(const uint32_t *src, void *dst);
static mesa_pack_uint_z_func
get_pack_uint_z_func(mesa_format format)
{
switch (format) {
case MESA_FORMAT_S8_UINT_Z24_UNORM:
case MESA_FORMAT_X8_UINT_Z24_UNORM:
return pack_uint_S8_UINT_Z24_UNORM;
case MESA_FORMAT_Z24_UNORM_S8_UINT:
case MESA_FORMAT_Z24_UNORM_X8_UINT:
return pack_uint_Z24_UNORM_S8_UINT;
case MESA_FORMAT_Z_UNORM16:
return pack_uint_Z_UNORM16;
case MESA_FORMAT_Z_UNORM32:
return pack_uint_Z_UNORM32;
case MESA_FORMAT_Z_FLOAT32:
case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
return pack_uint_Z_FLOAT32;
default:
unreachable("unexpected format in get_pack_uint_z_func()");
}
}
/**
* Put an array of 32-bit z values into the depth buffer.
* Note: the z values are always in the range [0, 2^32-1].
*/
static void
put_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLuint count, const GLint x[], const GLint y[],
const GLuint zvalues[], const GLubyte mask[])
{
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
const GLint w = rb->Width, h = rb->Height;
GLubyte *map = _swrast_pixel_address(rb, 0, 0);
GLuint i;
if (rb->Format == MESA_FORMAT_Z_UNORM32) {
const GLint rowStride = srb->RowStride;
for (i = 0; i < count; i++) {
if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
GLuint *dst = (GLuint *) (map + y[i] * rowStride + x[i] * 4);
*dst = zvalues[i];
}
}
}
else {
mesa_pack_uint_z_func packZ = get_pack_uint_z_func(rb->Format);
const GLint bpp = _mesa_get_format_bytes(rb->Format);
const GLint rowStride = srb->RowStride;
for (i = 0; i < count; i++) {
if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
void *dst = map + y[i] * rowStride + x[i] * bpp;
packZ(zvalues + i, dst);
}
}
}
}
/**
* Apply depth (Z) buffer testing to the span.
* \return approx number of pixels that passed (only zero is reliable)
*/
GLuint
_swrast_depth_test_span(struct gl_context *ctx, SWspan *span)
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
const GLint bpp = _mesa_get_format_bytes(rb->Format);
void *zStart;
const GLuint count = span->end;
const GLuint *fragZ = span->array->z;
GLubyte *mask = span->array->mask;
void *zBufferVals;
GLuint *zBufferTemp = NULL;
GLuint passed;
GLuint zBits = _mesa_get_format_bits(rb->Format, GL_DEPTH_BITS);
GLboolean ztest16 = GL_FALSE;
if (span->arrayMask & SPAN_XY)
zStart = NULL;
else
zStart = _swrast_pixel_address(rb, span->x, span->y);
if (rb->Format == MESA_FORMAT_Z_UNORM16 && !(span->arrayMask & SPAN_XY)) {
/* directly read/write row of 16-bit Z values */
zBufferVals = zStart;
ztest16 = GL_TRUE;
}
else if (rb->Format == MESA_FORMAT_Z_UNORM32 && !(span->arrayMask & SPAN_XY)) {
/* directly read/write row of 32-bit Z values */
zBufferVals = zStart;
}
else {
/* copy Z buffer values into temp buffer (32-bit Z values) */
zBufferTemp = malloc(count * sizeof(GLuint));
if (!zBufferTemp)
return 0;
if (span->arrayMask & SPAN_XY) {
get_z32_values(ctx, rb, count,
span->array->x, span->array->y, zBufferTemp);
}
else {
_mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp);
}
if (zBits == 24) {
GLuint i;
/* Convert depth buffer values from 32 to 24 bits to match the
* fragment Z values generated by rasterization.
*/
for (i = 0; i < count; i++) {
zBufferTemp[i] >>= 8;
}
}
else if (zBits == 16) {
GLuint i;
/* Convert depth buffer values from 32 to 16 bits */
for (i = 0; i < count; i++) {
zBufferTemp[i] >>= 16;
}
}
else {
assert(zBits == 32);
}
zBufferVals = zBufferTemp;
}
/* do the depth test either with 16 or 32-bit values */
if (ztest16)
passed = depth_test_span16(ctx, count, zBufferVals, fragZ, mask);
else
passed = depth_test_span32(ctx, count, zBufferVals, fragZ, mask);
if (zBufferTemp) {
/* need to write temp Z values back into the buffer */
/* Convert depth buffer values back to 32-bit values. The least
* significant bits don't matter since they'll get dropped when
* they're packed back into the depth buffer.
*/
if (zBits == 24) {
GLuint i;
for (i = 0; i < count; i++) {
zBufferTemp[i] = (zBufferTemp[i] << 8);
}
}
else if (zBits == 16) {
GLuint i;
for (i = 0; i < count; i++) {
zBufferTemp[i] = zBufferTemp[i] << 16;
}
}
if (span->arrayMask & SPAN_XY) {
/* random locations */
put_z32_values(ctx, rb, count, span->array->x, span->array->y,
zBufferTemp, mask);
}
else {
/* horizontal row */
mesa_pack_uint_z_func packZ = get_pack_uint_z_func(rb->Format);
GLubyte *dst = zStart;
GLuint i;
for (i = 0; i < count; i++) {
if (mask[i]) {
packZ(&zBufferTemp[i], dst);
}
dst += bpp;
}
}
free(zBufferTemp);
}
if (passed < count) {
span->writeAll = GL_FALSE;
}
return passed;
}
/**
* GL_EXT_depth_bounds_test extension.
* Discard fragments depending on whether the corresponding Z-buffer
* values are outside the depth bounds test range.
* Note: we test the Z buffer values, not the fragment Z values!
* \return GL_TRUE if any fragments pass, GL_FALSE if no fragments pass
*/
GLboolean
_swrast_depth_bounds_test( struct gl_context *ctx, SWspan *span )
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
GLubyte *zStart;
GLuint zMin = (GLuint)((double)ctx->Depth.BoundsMin * 0xffffffff);
GLuint zMax = (GLuint)((double)ctx->Depth.BoundsMax * 0xffffffff);
GLubyte *mask = span->array->mask;
const GLuint count = span->end;
GLuint i;
GLboolean anyPass = GL_FALSE;
GLuint *zBufferTemp;
const GLuint *zBufferVals;
zBufferTemp = malloc(count * sizeof(GLuint));
if (!zBufferTemp) {
/* don't generate a stream of OUT_OF_MEMORY errors here */
return GL_FALSE;
}
if (span->arrayMask & SPAN_XY)
zStart = NULL;
else
zStart = _swrast_pixel_address(rb, span->x, span->y);
if (rb->Format == MESA_FORMAT_Z_UNORM32 && !(span->arrayMask & SPAN_XY)) {
/* directly access 32-bit values in the depth buffer */
zBufferVals = (const GLuint *) zStart;
}
else {
/* Round the bounds to the precision of the zbuffer. */
if (rb->Format == MESA_FORMAT_Z_UNORM16) {
zMin = (zMin & 0xffff0000) | (zMin >> 16);
zMax = (zMax & 0xffff0000) | (zMax >> 16);
} else {
/* 24 bits */
zMin = (zMin & 0xffffff00) | (zMin >> 24);
zMax = (zMax & 0xffffff00) | (zMax >> 24);
}
/* unpack Z values into a temporary array */
if (span->arrayMask & SPAN_XY) {
get_z32_values(ctx, rb, count, span->array->x, span->array->y,
zBufferTemp);
}
else {
_mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp);
}
zBufferVals = zBufferTemp;
}
/* Now do the tests */
for (i = 0; i < count; i++) {
if (mask[i]) {
if (zBufferVals[i] < zMin || zBufferVals[i] > zMax)
mask[i] = GL_FALSE;
else
anyPass = GL_TRUE;
}
}
free(zBufferTemp);
return anyPass;
}
/**********************************************************************/
/***** Read Depth Buffer *****/
/**********************************************************************/
/**
* Read a span of depth values from the given depth renderbuffer, returning
* the values as GLfloats.
* This function does clipping to prevent reading outside the depth buffer's
* bounds.
*/
void
_swrast_read_depth_span_float(struct gl_context *ctx,
struct gl_renderbuffer *rb,
GLint n, GLint x, GLint y, GLfloat depth[])
{
if (!rb) {
/* really only doing this to prevent FP exceptions later */
memset(depth, 0, n * sizeof(GLfloat));
return;
}
if (y < 0 || y >= (GLint) rb->Height ||
x + n <= 0 || x >= (GLint) rb->Width) {
/* span is completely outside framebuffer */
memset(depth, 0, n * sizeof(GLfloat));
return;
}
if (x < 0) {
GLint dx = -x;
GLint i;
for (i = 0; i < dx; i++)
depth[i] = 0.0;
x = 0;
n -= dx;
depth += dx;
}
if (x + n > (GLint) rb->Width) {
GLint dx = x + n - (GLint) rb->Width;
GLint i;
for (i = 0; i < dx; i++)
depth[n - i - 1] = 0.0;
n -= dx;
}
if (n <= 0) {
return;
}
_mesa_unpack_float_z_row(rb->Format, n, _swrast_pixel_address(rb, x, y),
depth);
}
/**
* Clear the given z/depth renderbuffer. If the buffer is a combined
* depth+stencil buffer, only the Z bits will be touched.
*/
void
_swrast_clear_depth_buffer(struct gl_context *ctx)
{
struct gl_renderbuffer *rb =
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
GLint x, y, width, height;
GLubyte *map;
GLint rowStride, i, j;
GLbitfield mapMode;
if (!rb || !ctx->Depth.Mask) {
/* no depth buffer, or writing to it is disabled */
return;
}
/* compute region to clear */
x = ctx->DrawBuffer->_Xmin;
y = ctx->DrawBuffer->_Ymin;
width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
mapMode = GL_MAP_WRITE_BIT;
if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT ||
rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT ||
rb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM ||
rb->Format == MESA_FORMAT_X8_UINT_Z24_UNORM) {
mapMode |= GL_MAP_READ_BIT;
}
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
mapMode, &map, &rowStride,
ctx->DrawBuffer->FlipY);
if (!map) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth)");
return;
}
switch (rb->Format) {
case MESA_FORMAT_Z_UNORM16:
{
GLfloat clear = (GLfloat) ctx->Depth.Clear;
GLushort clearVal = 0;
_mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal);
if (clearVal == 0xffff && width * 2 == rowStride) {
/* common case */
memset(map, 0xff, width * height * 2);
}
else {
for (i = 0; i < height; i++) {
GLushort *row = (GLushort *) map;
for (j = 0; j < width; j++) {
row[j] = clearVal;
}
map += rowStride;
}
}
}
break;
case MESA_FORMAT_Z_UNORM32:
case MESA_FORMAT_Z_FLOAT32:
{
GLfloat clear = (GLfloat) ctx->Depth.Clear;
GLuint clearVal = 0;
_mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal);
for (i = 0; i < height; i++) {
GLuint *row = (GLuint *) map;
for (j = 0; j < width; j++) {
row[j] = clearVal;
}
map += rowStride;
}
}
break;
case MESA_FORMAT_Z24_UNORM_S8_UINT:
case MESA_FORMAT_Z24_UNORM_X8_UINT:
case MESA_FORMAT_S8_UINT_Z24_UNORM:
case MESA_FORMAT_X8_UINT_Z24_UNORM:
{
GLfloat clear = (GLfloat) ctx->Depth.Clear;
GLuint clearVal = 0;
GLuint mask;
if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT ||
rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT)
mask = 0xff000000;
else
mask = 0xff;
_mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal);
for (i = 0; i < height; i++) {
GLuint *row = (GLuint *) map;
for (j = 0; j < width; j++) {
row[j] = (row[j] & mask) | clearVal;
}
map += rowStride;
}
}
break;
case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
/* XXX untested */
{
GLfloat clearVal = (GLfloat) ctx->Depth.Clear;
for (i = 0; i < height; i++) {
GLfloat *row = (GLfloat *) map;
for (j = 0; j < width; j++) {
row[j * 2] = clearVal;
}
map += rowStride;
}
}
break;
default:
_mesa_problem(ctx, "Unexpected depth buffer format %s"
" in _swrast_clear_depth_buffer()",
_mesa_get_format_name(rb->Format));
}
ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
/**
* Clear both depth and stencil values in a combined depth+stencil buffer.
*/
void
_swrast_clear_depth_stencil_buffer(struct gl_context *ctx)
{
const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
const GLuint writeMask = ctx->Stencil.WriteMask[0];
const GLuint stencilMax = (1 << stencilBits) - 1;
struct gl_renderbuffer *rb =
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
GLint x, y, width, height;
GLbitfield mapMode;
GLubyte *map;
GLint rowStride, i, j;
/* check that we really have a combined depth+stencil buffer */
assert(rb == ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer);
/* compute region to clear */
x = ctx->DrawBuffer->_Xmin;
y = ctx->DrawBuffer->_Ymin;
width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
mapMode = GL_MAP_WRITE_BIT;
if ((writeMask & stencilMax) != stencilMax) {
/* need to mask stencil values */
mapMode |= GL_MAP_READ_BIT;
}
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
mapMode, &map, &rowStride,
ctx->DrawBuffer->FlipY);
if (!map) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth+stencil)");
return;
}
switch (rb->Format) {
case MESA_FORMAT_Z24_UNORM_S8_UINT:
case MESA_FORMAT_S8_UINT_Z24_UNORM:
{
GLfloat zClear = (GLfloat) ctx->Depth.Clear;
GLuint clear = 0, mask;
_mesa_pack_float_z_row(rb->Format, 1, &zClear, &clear);
if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) {
mask = ((~writeMask) & 0xff) << 24;
clear |= (ctx->Stencil.Clear & writeMask & 0xff) << 24;
}
else {
mask = ((~writeMask) & 0xff);
clear |= (ctx->Stencil.Clear & writeMask & 0xff);
}
for (i = 0; i < height; i++) {
GLuint *row = (GLuint *) map;
if (mask != 0x0) {
for (j = 0; j < width; j++) {
row[j] = (row[j] & mask) | clear;
}
}
else {
for (j = 0; j < width; j++) {
row[j] = clear;
}
}
map += rowStride;
}
}
break;
case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
/* XXX untested */
{
const GLfloat zClear = (GLfloat) ctx->Depth.Clear;
const GLuint sClear = ctx->Stencil.Clear & writeMask;
const GLuint sMask = (~writeMask) & 0xff;
for (i = 0; i < height; i++) {
GLfloat *zRow = (GLfloat *) map;
GLuint *sRow = (GLuint *) map;
for (j = 0; j < width; j++) {
zRow[j * 2 + 0] = zClear;
}
if (sMask != 0) {
for (j = 0; j < width; j++) {
sRow[j * 2 + 1] = (sRow[j * 2 + 1] & sMask) | sClear;
}
}
else {
for (j = 0; j < width; j++) {
sRow[j * 2 + 1] = sClear;
}
}
map += rowStride;
}
}
break;
default:
_mesa_problem(ctx, "Unexpected depth buffer format %s"
" in _swrast_clear_depth_buffer()",
_mesa_get_format_name(rb->Format));
}
ctx->Driver.UnmapRenderbuffer(ctx, rb);
}

View File

@ -1,58 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_DEPTH_H
#define S_DEPTH_H
#include "main/glheader.h"
#include "s_span.h"
struct gl_context;
struct gl_renderbuffer;
extern GLuint
_swrast_depth_test_span( struct gl_context *ctx, SWspan *span);
extern void
_swrast_depth_clamp_span( struct gl_context *ctx, SWspan *span );
extern GLboolean
_swrast_depth_bounds_test( struct gl_context *ctx, SWspan *span );
extern void
_swrast_read_depth_span_float( struct gl_context *ctx, struct gl_renderbuffer *rb,
GLint n, GLint x, GLint y, GLfloat depth[] );
extern void
_swrast_clear_depth_buffer(struct gl_context *ctx);
extern void
_swrast_clear_depth_stencil_buffer(struct gl_context *ctx);
#endif

View File

@ -1,791 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/bufferobj.h"
#include "main/colormac.h"
#include "main/condrender.h"
#include "main/context.h"
#include "main/format_pack.h"
#include "main/format_utils.h"
#include "main/glformats.h"
#include "main/image.h"
#include "main/macros.h"
#include "main/pack.h"
#include "main/pbo.h"
#include "main/pixeltransfer.h"
#include "main/state.h"
#include "s_context.h"
#include "s_span.h"
#include "s_stencil.h"
#include "s_zoom.h"
/**
* Handle a common case of drawing GL_RGB/GL_UNSIGNED_BYTE into a
* MESA_FORMAT_XRGB888 or MESA_FORMAT_ARGB888 renderbuffer.
*/
static void
fast_draw_rgb_ubyte_pixels(struct gl_context *ctx,
struct gl_renderbuffer *rb,
GLint x, GLint y,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels,
bool flip_y)
{
const GLubyte *src = (const GLubyte *)
_mesa_image_address2d(unpack, pixels, width,
height, GL_RGB, GL_UNSIGNED_BYTE, 0, 0);
const GLint srcRowStride = _mesa_image_row_stride(unpack, width,
GL_RGB, GL_UNSIGNED_BYTE);
GLint i, j;
GLubyte *dst;
GLint dstRowStride;
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
GL_MAP_WRITE_BIT, &dst, &dstRowStride,
flip_y);
if (!dst) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
if (ctx->Pixel.ZoomY == -1.0f) {
dst = dst + (height - 1) * dstRowStride;
dstRowStride = -dstRowStride;
}
for (i = 0; i < height; i++) {
GLuint *dst4 = (GLuint *) dst;
for (j = 0; j < width; j++) {
dst4[j] = PACK_COLOR_8888(0xff, src[j*3+0], src[j*3+1], src[j*3+2]);
}
dst += dstRowStride;
src += srcRowStride;
}
ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
/**
* Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a
* MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer.
*/
static void
fast_draw_rgba_ubyte_pixels(struct gl_context *ctx,
struct gl_renderbuffer *rb,
GLint x, GLint y,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels,
bool flip_y)
{
const GLubyte *src = (const GLubyte *)
_mesa_image_address2d(unpack, pixels, width,
height, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
const GLint srcRowStride =
_mesa_image_row_stride(unpack, width, GL_RGBA, GL_UNSIGNED_BYTE);
GLint i, j;
GLubyte *dst;
GLint dstRowStride;
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
GL_MAP_WRITE_BIT, &dst, &dstRowStride,
flip_y);
if (!dst) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
if (ctx->Pixel.ZoomY == -1.0f) {
dst = dst + (height - 1) * dstRowStride;
dstRowStride = -dstRowStride;
}
for (i = 0; i < height; i++) {
GLuint *dst4 = (GLuint *) dst;
for (j = 0; j < width; j++) {
dst4[j] = PACK_COLOR_8888(src[j*4+3], src[j*4+0],
src[j*4+1], src[j*4+2]);
}
dst += dstRowStride;
src += srcRowStride;
}
ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
/**
* Handle a common case of drawing a format/type combination that
* exactly matches the renderbuffer format.
*/
static void
fast_draw_generic_pixels(struct gl_context *ctx,
struct gl_renderbuffer *rb,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels,
bool flip_y)
{
const GLubyte *src = (const GLubyte *)
_mesa_image_address2d(unpack, pixels, width,
height, format, type, 0, 0);
const GLint srcRowStride =
_mesa_image_row_stride(unpack, width, format, type);
const GLint rowLength = width * _mesa_get_format_bytes(rb->Format);
GLint i;
GLubyte *dst;
GLint dstRowStride;
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
GL_MAP_WRITE_BIT, &dst, &dstRowStride,
flip_y);
if (!dst) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
if (ctx->Pixel.ZoomY == -1.0f) {
dst = dst + (height - 1) * dstRowStride;
dstRowStride = -dstRowStride;
}
for (i = 0; i < height; i++) {
memcpy(dst, src, rowLength);
dst += dstRowStride;
src += srcRowStride;
}
ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
/**
* Try to do a fast and simple RGB(a) glDrawPixels.
* Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
*/
static GLboolean
fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *userUnpack,
const GLvoid *pixels)
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_pixelstore_attrib unpack;
if (!rb)
return GL_TRUE; /* no-op */
if (ctx->DrawBuffer->_NumColorDrawBuffers > 1 ||
(swrast->_RasterMask & ~CLIP_BIT) ||
ctx->Texture._EnabledCoordUnits ||
userUnpack->SwapBytes ||
ctx->Pixel.ZoomX != 1.0f ||
fabsf(ctx->Pixel.ZoomY) != 1.0f ||
ctx->_ImageTransferState) {
/* can't handle any of those conditions */
return GL_FALSE;
}
unpack = *userUnpack;
/* clipping */
if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &unpack)) {
/* image was completely clipped: no-op, all done */
return GL_TRUE;
}
if (format == GL_RGB &&
type == GL_UNSIGNED_BYTE &&
(rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
fast_draw_rgb_ubyte_pixels(ctx, rb, x, y, width, height,
&unpack, pixels, fb->FlipY);
return GL_TRUE;
}
if (format == GL_RGBA &&
type == GL_UNSIGNED_BYTE &&
(rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
fast_draw_rgba_ubyte_pixels(ctx, rb, x, y, width, height,
&unpack, pixels, fb->FlipY);
return GL_TRUE;
}
if (_mesa_format_matches_format_and_type(rb->Format, format, type,
ctx->Unpack.SwapBytes, NULL)) {
fast_draw_generic_pixels(ctx, rb, x, y, width, height,
format, type, &unpack, pixels,
fb->FlipY);
return GL_TRUE;
}
/* can't handle this pixel format and/or data type */
return GL_FALSE;
}
/*
* Draw stencil image.
*/
static void
draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
const GLenum destType = GL_UNSIGNED_BYTE;
GLint row;
GLubyte *values;
values = malloc(width * sizeof(GLubyte));
if (!values) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
for (row = 0; row < height; row++) {
const GLvoid *source = _mesa_image_address2d(unpack, pixels,
width, height,
GL_STENCIL_INDEX, type,
row, 0);
_mesa_unpack_stencil_span(ctx, width, destType, values,
type, source, unpack,
ctx->_ImageTransferState);
if (zoom) {
_swrast_write_zoomed_stencil_span(ctx, x, y, width,
x, y, values);
}
else {
_swrast_write_stencil_span(ctx, width, x, y, values);
}
y++;
}
free(values);
}
/*
* Draw depth image.
*/
static void
draw_depth_pixels( struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
const GLboolean scaleOrBias
= ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0f || ctx->Pixel.ZoomY != 1.0f;
SWspan span;
INIT_SPAN(span, GL_BITMAP);
span.arrayMask = SPAN_Z;
_swrast_span_default_attribs(ctx, &span);
if (type == GL_UNSIGNED_SHORT
&& ctx->DrawBuffer->Visual.depthBits == 16
&& !scaleOrBias
&& !zoom
&& width <= SWRAST_MAX_WIDTH
&& !unpack->SwapBytes) {
/* Special case: directly write 16-bit depth values */
GLint row;
for (row = 0; row < height; row++) {
const GLushort *zSrc = (const GLushort *)
_mesa_image_address2d(unpack, pixels, width, height,
GL_DEPTH_COMPONENT, type, row, 0);
GLint i;
for (i = 0; i < width; i++)
span.array->z[i] = zSrc[i];
span.x = x;
span.y = y + row;
span.end = width;
_swrast_write_rgba_span(ctx, &span);
}
}
else if (type == GL_UNSIGNED_INT
&& !scaleOrBias
&& !zoom
&& width <= SWRAST_MAX_WIDTH
&& !unpack->SwapBytes) {
/* Special case: shift 32-bit values down to Visual.depthBits */
const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits;
GLint row;
for (row = 0; row < height; row++) {
const GLuint *zSrc = (const GLuint *)
_mesa_image_address2d(unpack, pixels, width, height,
GL_DEPTH_COMPONENT, type, row, 0);
if (shift == 0) {
memcpy(span.array->z, zSrc, width * sizeof(GLuint));
}
else {
GLint col;
for (col = 0; col < width; col++)
span.array->z[col] = zSrc[col] >> shift;
}
span.x = x;
span.y = y + row;
span.end = width;
_swrast_write_rgba_span(ctx, &span);
}
}
else {
/* General case */
const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
GLint skipPixels = 0;
/* in case width > SWRAST_MAX_WIDTH do the copy in chunks */
while (skipPixels < width) {
const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
GLint row;
assert(span.end <= SWRAST_MAX_WIDTH);
for (row = 0; row < height; row++) {
const GLvoid *zSrc = _mesa_image_address2d(unpack,
pixels, width, height,
GL_DEPTH_COMPONENT, type,
row, skipPixels);
/* Set these for each row since the _swrast_write_* function may
* change them while clipping.
*/
span.x = x + skipPixels;
span.y = y + row;
span.end = spanWidth;
_mesa_unpack_depth_span(ctx, spanWidth,
GL_UNSIGNED_INT, span.array->z, depthMax,
type, zSrc, unpack);
if (zoom) {
_swrast_write_zoomed_depth_span(ctx, x, y, &span);
}
else {
_swrast_write_rgba_span(ctx, &span);
}
}
skipPixels += spanWidth;
}
}
}
/**
* Draw RGBA image.
*/
static void
draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
const GLint imgX = x, imgY = y;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
GLbitfield transferOps = ctx->_ImageTransferState;
SWspan span;
/* Try an optimized glDrawPixels first */
if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type,
unpack, pixels)) {
return;
}
swrast_render_start(ctx);
INIT_SPAN(span, GL_BITMAP);
_swrast_span_default_attribs(ctx, &span);
span.arrayMask = SPAN_RGBA;
span.arrayAttribs = VARYING_BIT_COL0; /* we're fill in COL0 attrib values */
if (ctx->DrawBuffer->_NumColorDrawBuffers > 0) {
GLenum datatype = _mesa_get_format_datatype(
ctx->DrawBuffer->_ColorDrawBuffers[0]->Format);
if (datatype != GL_FLOAT &&
ctx->Color.ClampFragmentColor != GL_FALSE) {
/* need to clamp colors before applying fragment ops */
transferOps |= IMAGE_CLAMP_BIT;
}
}
/*
* General solution
*/
{
const GLbitfield interpMask = span.interpMask;
const GLbitfield arrayMask = span.arrayMask;
GLint skipPixels = 0;
/* use span array for temp color storage */
GLfloat *rgba = (GLfloat *) span.array->attribs[VARYING_SLOT_COL0];
void *tempImage = NULL;
/* We have to deal with GL_COLOR_INDEX manually because
* _mesa_format_convert does not handle this format. So what we do here is
* convert it to RGBA ubyte first and then convert from that to dst as
* usual.
*/
if (format == GL_COLOR_INDEX) {
/* This will handle byte swapping and transferops if needed */
tempImage =
_mesa_unpack_color_index_to_rgba_ubyte(ctx, 2,
pixels, format, type,
width, height, 1,
unpack,
transferOps);
if (!tempImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
transferOps = 0;
pixels = tempImage;
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
} else if (unpack->SwapBytes) {
/* We have to handle byte-swapping scenarios before calling
* _mesa_format_convert
*/
GLint swapSize = _mesa_sizeof_packed_type(type);
if (swapSize == 2 || swapSize == 4) {
int imageStride = _mesa_image_image_stride(unpack, width, height, format, type);
tempImage = malloc(imageStride);
if (!tempImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
_mesa_swap_bytes_2d_image(format, type, unpack,
width, height, tempImage, pixels);
pixels = tempImage;
}
}
const GLint srcStride
= _mesa_image_row_stride(unpack, width, format, type);
/* if the span is wider than SWRAST_MAX_WIDTH we have to do it in chunks */
while (skipPixels < width) {
const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
const GLubyte *source
= (const GLubyte *) _mesa_image_address2d(unpack, pixels,
width, height, format,
type, 0, skipPixels);
GLint row;
/* get image row as float/RGBA */
uint32_t srcMesaFormat = _mesa_format_from_format_and_type(format, type);
for (row = 0; row < height; row++) {
int dstRowStride = 4 * width * sizeof(float);
_mesa_format_convert(rgba, RGBA32_FLOAT, dstRowStride,
(void*)source, srcMesaFormat, srcStride,
spanWidth, 1, NULL);
if (transferOps)
_mesa_apply_rgba_transfer_ops(ctx, transferOps, spanWidth, (GLfloat (*)[4])rgba);
/* Set these for each row since the _swrast_write_* functions
* may change them while clipping/rendering.
*/
span.array->ChanType = GL_FLOAT;
span.x = x + skipPixels;
span.y = y + row;
span.end = spanWidth;
span.arrayMask = arrayMask;
span.interpMask = interpMask;
if (zoom) {
_swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
}
else {
_swrast_write_rgba_span(ctx, &span);
}
source += srcStride;
} /* for row */
skipPixels += spanWidth;
} /* while skipPixels < width */
/* XXX this is ugly/temporary, to undo above change */
span.array->ChanType = CHAN_TYPE;
free(tempImage);
}
swrast_render_finish(ctx);
}
/**
* Incoming Z/stencil values are always in uint_24_8 format.
*/
static void
pack_uint_24_8_depth_stencil_row(mesa_format format, uint32_t n,
const uint32_t *src, void *dst)
{
switch (format) {
case MESA_FORMAT_S8_UINT_Z24_UNORM:
memcpy(dst, src, n * sizeof(uint32_t));
break;
case MESA_FORMAT_Z24_UNORM_S8_UINT:
{
uint32_t *d = ((uint32_t *) dst);
uint32_t i;
for (i = 0; i < n; i++) {
uint32_t s = src[i] << 24;
uint32_t z = src[i] >> 8;
d[i] = s | z;
}
}
break;
default:
unreachable("bad format in _mesa_pack_ubyte_s_row");
}
}
/**
* Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_Z24_UNORM_S8_UINT
* renderbuffer. No masking, zooming, scaling, etc.
*/
static void
fast_draw_depth_stencil(struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels)
{
const GLenum format = GL_DEPTH_STENCIL_EXT;
const GLenum type = GL_UNSIGNED_INT_24_8;
struct gl_renderbuffer *rb =
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
GLubyte *src, *dst;
GLint srcRowStride, dstRowStride;
GLint i;
src = _mesa_image_address2d(unpack, pixels, width, height,
format, type, 0, 0);
srcRowStride = _mesa_image_row_stride(unpack, width, format, type);
dst = _swrast_pixel_address(rb, x, y);
dstRowStride = srb->RowStride;
for (i = 0; i < height; i++) {
pack_uint_24_8_depth_stencil_row(rb->Format, width, (const GLuint *) src, dst);
dst += dstRowStride;
src += srcRowStride;
}
}
/**
* This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
* The only per-pixel operations that apply are depth scale/bias,
* stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
* and pixel zoom.
* Also, only the depth buffer and stencil buffers are touched, not the
* color buffer(s).
*/
static void
draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels)
{
const GLint imgX = x, imgY = y;
const GLboolean scaleOrBias
= ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
const GLuint stencilMask = ctx->Stencil.WriteMask[0];
const GLenum stencilType = GL_UNSIGNED_BYTE;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
struct gl_renderbuffer *depthRb, *stencilRb;
struct gl_pixelstore_attrib clippedUnpack = *unpack;
if (!zoom) {
if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
&clippedUnpack)) {
/* totally clipped */
return;
}
}
depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
assert(depthRb);
assert(stencilRb);
if (depthRb == stencilRb &&
(depthRb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM ||
depthRb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) &&
type == GL_UNSIGNED_INT_24_8 &&
!scaleOrBias &&
!zoom &&
ctx->Depth.Mask &&
(stencilMask & 0xff) == 0xff) {
fast_draw_depth_stencil(ctx, x, y, width, height,
&clippedUnpack, pixels);
}
else {
/* sub-optimal cases:
* Separate depth/stencil buffers, or pixel transfer ops required.
*/
/* XXX need to handle very wide images (skippixels) */
GLuint *zValues; /* 32-bit Z values */
GLint i;
zValues = malloc(width * sizeof(GLuint));
if (!zValues) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
return;
}
for (i = 0; i < height; i++) {
const GLuint *depthStencilSrc = (const GLuint *)
_mesa_image_address2d(&clippedUnpack, pixels, width, height,
GL_DEPTH_STENCIL_EXT, type, i, 0);
if (ctx->Depth.Mask) {
_mesa_unpack_depth_span(ctx, width,
GL_UNSIGNED_INT, /* dest type */
zValues, /* dest addr */
0xffffffff, /* depth max */
type, /* src type */
depthStencilSrc, /* src addr */
&clippedUnpack);
if (zoom) {
_swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
y + i, zValues);
}
else {
GLubyte *dst = _swrast_pixel_address(depthRb, x, y + i);
_mesa_pack_uint_z_row(depthRb->Format, width, zValues, dst);
}
}
if (stencilMask != 0x0) {
GLubyte *stencilValues = (GLubyte *) zValues; /* re-use buffer */
/* get stencil values, with shift/offset/mapping */
_mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues,
type, depthStencilSrc, &clippedUnpack,
ctx->_ImageTransferState);
if (zoom)
_swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width,
x, y + i, stencilValues);
else
_swrast_write_stencil_span(ctx, width, x, y + i, stencilValues);
}
}
free(zValues);
}
}
/**
* Execute software-based glDrawPixels.
* By time we get here, all error checking will have been done.
*/
void
_swrast_DrawPixels( struct gl_context *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLboolean save_vp_override = ctx->VertexProgram._Overriden;
if (!_mesa_check_conditional_render(ctx))
return; /* don't draw */
/* We are creating fragments directly, without going through vertex
* programs.
*
* This override flag tells the fragment processing code that its input
* comes from a non-standard source, and it may therefore not rely on
* optimizations that assume e.g. constant color if there is no color
* vertex array.
*/
_mesa_set_vp_override(ctx, GL_TRUE);
if (ctx->NewState)
_mesa_update_state(ctx);
if (swrast->NewState)
_swrast_validate_derived( ctx );
pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
if (!pixels) {
_mesa_set_vp_override(ctx, save_vp_override);
return;
}
/*
* By time we get here, all error checking should have been done.
*/
switch (format) {
case GL_STENCIL_INDEX:
swrast_render_start(ctx);
draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
swrast_render_finish(ctx);
break;
case GL_DEPTH_COMPONENT:
swrast_render_start(ctx);
draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
swrast_render_finish(ctx);
break;
case GL_DEPTH_STENCIL_EXT:
swrast_render_start(ctx);
draw_depth_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
swrast_render_finish(ctx);
break;
default:
/* all other formats should be color formats */
draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
}
_mesa_set_vp_override(ctx, save_vp_override);
_mesa_unmap_pbo_source(ctx, unpack);
}

View File

@ -1,137 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/feedback.h"
#include "main/macros.h"
#include "s_context.h"
#include "s_feedback.h"
#include "s_triangle.h"
static void
feedback_vertex(struct gl_context * ctx, const SWvertex * v, const SWvertex * pv)
{
GLfloat win[4];
const GLfloat *vtc = v->attrib[VARYING_SLOT_TEX0];
const GLfloat *color = v->attrib[VARYING_SLOT_COL0];
win[0] = v->attrib[VARYING_SLOT_POS][0];
win[1] = v->attrib[VARYING_SLOT_POS][1];
win[2] = v->attrib[VARYING_SLOT_POS][2] / ctx->DrawBuffer->_DepthMaxF;
win[3] = 1.0F / v->attrib[VARYING_SLOT_POS][3];
_mesa_feedback_vertex(ctx, win, color, vtc);
}
/*
* Put triangle in feedback buffer.
*/
void
_swrast_feedback_triangle(struct gl_context *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2)
{
if (!_swrast_culltriangle(ctx, v0, v1, v2)) {
_mesa_feedback_token(ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN);
_mesa_feedback_token(ctx, (GLfloat) 3); /* three vertices */
if (ctx->Light.ShadeModel == GL_SMOOTH) {
feedback_vertex(ctx, v0, v0);
feedback_vertex(ctx, v1, v1);
feedback_vertex(ctx, v2, v2);
}
else {
feedback_vertex(ctx, v0, v2);
feedback_vertex(ctx, v1, v2);
feedback_vertex(ctx, v2, v2);
}
}
}
void
_swrast_feedback_line(struct gl_context *ctx, const SWvertex *v0,
const SWvertex *v1)
{
GLenum token = GL_LINE_TOKEN;
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->StippleCounter == 0)
token = GL_LINE_RESET_TOKEN;
_mesa_feedback_token(ctx, (GLfloat) (GLint) token);
if (ctx->Light.ShadeModel == GL_SMOOTH) {
feedback_vertex(ctx, v0, v0);
feedback_vertex(ctx, v1, v1);
}
else {
feedback_vertex(ctx, v0, v1);
feedback_vertex(ctx, v1, v1);
}
swrast->StippleCounter++;
}
void
_swrast_feedback_point(struct gl_context *ctx, const SWvertex *v)
{
_mesa_feedback_token(ctx, (GLfloat) (GLint) GL_POINT_TOKEN);
feedback_vertex(ctx, v, v);
}
void
_swrast_select_triangle(struct gl_context *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2)
{
if (!_swrast_culltriangle(ctx, v0, v1, v2)) {
const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
_mesa_update_hitflag( ctx, v0->attrib[VARYING_SLOT_POS][2] * zs );
_mesa_update_hitflag( ctx, v1->attrib[VARYING_SLOT_POS][2] * zs );
_mesa_update_hitflag( ctx, v2->attrib[VARYING_SLOT_POS][2] * zs );
}
}
void
_swrast_select_line(struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1)
{
const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
_mesa_update_hitflag( ctx, v0->attrib[VARYING_SLOT_POS][2] * zs );
_mesa_update_hitflag( ctx, v1->attrib[VARYING_SLOT_POS][2] * zs );
}
void
_swrast_select_point(struct gl_context *ctx, const SWvertex *v)
{
const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
_mesa_update_hitflag( ctx, v->attrib[VARYING_SLOT_POS][2] * zs );
}

View File

@ -1,50 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_FEEDBACK_H
#define S_FEEDBACK_H
#include "swrast.h"
extern void _swrast_feedback_point( struct gl_context *ctx, const SWvertex *v );
extern void _swrast_feedback_line( struct gl_context *ctx,
const SWvertex *v1, const SWvertex *v2 );
extern void _swrast_feedback_triangle( struct gl_context *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2 );
extern void _swrast_select_point( struct gl_context *ctx, const SWvertex *v );
extern void _swrast_select_line( struct gl_context *ctx,
const SWvertex *v1, const SWvertex *v2 );
extern void _swrast_select_triangle( struct gl_context *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2 );
#endif

View File

@ -1,245 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "c99_math.h"
#include "main/errors.h"
#include "main/glheader.h"
#include "main/macros.h"
#include "s_context.h"
#include "s_fog.h"
/**
* Used to convert current raster distance to a fog factor in [0,1].
*/
GLfloat
_swrast_z_to_fogfactor(struct gl_context *ctx, GLfloat z)
{
GLfloat d, f;
switch (ctx->Fog.Mode) {
case GL_LINEAR:
if (ctx->Fog.Start == ctx->Fog.End)
d = 1.0F;
else
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
f = (ctx->Fog.End - z) * d;
return CLAMP(f, 0.0F, 1.0F);
case GL_EXP:
d = ctx->Fog.Density;
f = expf(-d * z);
f = CLAMP(f, 0.0F, 1.0F);
return f;
case GL_EXP2:
d = ctx->Fog.Density;
f = expf(-(d * d * z * z));
f = CLAMP(f, 0.0F, 1.0F);
return f;
default:
_mesa_problem(ctx, "Bad fog mode in _swrast_z_to_fogfactor");
return 0.0;
}
}
#define LINEAR_FOG(f, coord) f = (fogEnd - coord) * fogScale
#define EXP_FOG(f, coord) f = expf(density * coord)
#define EXP2_FOG(f, coord) \
do { \
GLfloat tmp = negDensitySquared * coord * coord; \
if (tmp < FLT_MIN_10_EXP) \
tmp = FLT_MIN_10_EXP; \
f = expf(tmp); \
} while(0)
#define BLEND_FOG(f, coord) f = coord
/**
* Template code for computing fog blend factor and applying it to colors.
* \param TYPE either GLubyte, GLushort or GLfloat.
* \param COMPUTE_F code to compute the fog blend factor, f.
*/
#define FOG_LOOP(TYPE, FOG_FUNC) \
if (span->arrayAttribs & VARYING_BIT_FOGC) { \
GLuint i; \
for (i = 0; i < span->end; i++) { \
const GLfloat fogCoord = span->array->attribs[VARYING_SLOT_FOGC][i][0]; \
const GLfloat c = fabsf(fogCoord); \
GLfloat f, oneMinusF; \
FOG_FUNC(f, c); \
f = CLAMP(f, 0.0F, 1.0F); \
oneMinusF = 1.0F - f; \
rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \
rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \
rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \
} \
} \
else { \
const GLfloat fogStep = span->attrStepX[VARYING_SLOT_FOGC][0]; \
GLfloat fogCoord = span->attrStart[VARYING_SLOT_FOGC][0]; \
const GLfloat wStep = span->attrStepX[VARYING_SLOT_POS][3]; \
GLfloat w = span->attrStart[VARYING_SLOT_POS][3]; \
GLuint i; \
for (i = 0; i < span->end; i++) { \
const GLfloat c = fabsf(fogCoord) / w; \
GLfloat f, oneMinusF; \
FOG_FUNC(f, c); \
f = CLAMP(f, 0.0F, 1.0F); \
oneMinusF = 1.0F - f; \
rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \
rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \
rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \
fogCoord += fogStep; \
w += wStep; \
} \
}
/**
* Apply fog to a span of RGBA pixels.
* The fog value are either in the span->array->fog array or interpolated from
* the fog/fogStep values.
* They fog values are either fog coordinates (Z) or fog blend factors.
* _PreferPixelFog should be in sync with that state!
*/
void
_swrast_fog_rgba_span( const struct gl_context *ctx, SWspan *span )
{
const SWcontext *swrast = CONST_SWRAST_CONTEXT(ctx);
GLfloat rFog, gFog, bFog;
assert(swrast->_FogEnabled);
assert(span->arrayMask & SPAN_RGBA);
/* compute (scaled) fog color */
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
rFog = ctx->Fog.Color[RCOMP] * 255.0F;
gFog = ctx->Fog.Color[GCOMP] * 255.0F;
bFog = ctx->Fog.Color[BCOMP] * 255.0F;
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
rFog = ctx->Fog.Color[RCOMP] * 65535.0F;
gFog = ctx->Fog.Color[GCOMP] * 65535.0F;
bFog = ctx->Fog.Color[BCOMP] * 65535.0F;
}
else {
rFog = ctx->Fog.Color[RCOMP];
gFog = ctx->Fog.Color[GCOMP];
bFog = ctx->Fog.Color[BCOMP];
}
if (swrast->_PreferPixelFog) {
/* The span's fog values are fog coordinates, now compute blend factors
* and blend the fragment colors with the fog color.
*/
switch (ctx->Fog.Mode) {
case GL_LINEAR:
{
const GLfloat fogEnd = ctx->Fog.End;
const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End)
? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start);
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
GLubyte (*rgba)[4] = span->array->rgba8;
FOG_LOOP(GLubyte, LINEAR_FOG);
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
GLushort (*rgba)[4] = span->array->rgba16;
FOG_LOOP(GLushort, LINEAR_FOG);
}
else {
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
assert(span->array->ChanType == GL_FLOAT);
FOG_LOOP(GLfloat, LINEAR_FOG);
}
}
break;
case GL_EXP:
{
const GLfloat density = -ctx->Fog.Density;
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
GLubyte (*rgba)[4] = span->array->rgba8;
FOG_LOOP(GLubyte, EXP_FOG);
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
GLushort (*rgba)[4] = span->array->rgba16;
FOG_LOOP(GLushort, EXP_FOG);
}
else {
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
assert(span->array->ChanType == GL_FLOAT);
FOG_LOOP(GLfloat, EXP_FOG);
}
}
break;
case GL_EXP2:
{
const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
GLubyte (*rgba)[4] = span->array->rgba8;
FOG_LOOP(GLubyte, EXP2_FOG);
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
GLushort (*rgba)[4] = span->array->rgba16;
FOG_LOOP(GLushort, EXP2_FOG);
}
else {
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
assert(span->array->ChanType == GL_FLOAT);
FOG_LOOP(GLfloat, EXP2_FOG);
}
}
break;
default:
_mesa_problem(ctx, "Bad fog mode in _swrast_fog_rgba_span");
return;
}
}
else {
/* The span's fog start/step/array values are blend factors in [0,1].
* They were previously computed per-vertex.
*/
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
GLubyte (*rgba)[4] = span->array->rgba8;
FOG_LOOP(GLubyte, BLEND_FOG);
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
GLushort (*rgba)[4] = span->array->rgba16;
FOG_LOOP(GLushort, BLEND_FOG);
}
else {
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
assert(span->array->ChanType == GL_FLOAT);
FOG_LOOP(GLfloat, BLEND_FOG);
}
}
}

View File

@ -1,42 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_FOG_H
#define S_FOG_H
#include "main/glheader.h"
#include "s_span.h"
struct gl_context;
extern GLfloat
_swrast_z_to_fogfactor(struct gl_context *ctx, GLfloat z);
extern void
_swrast_fog_rgba_span( const struct gl_context *ctx, SWspan *span );
#endif

View File

@ -1,284 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/macros.h"
#include "main/samplerobj.h"
#include "main/teximage.h"
#include "program/prog_instruction.h"
#include "s_context.h"
#include "s_fragprog.h"
#include "s_span.h"
/**
* \brief Should swrast use a fragment program?
*
* \return true if the current fragment program exists and is not the fixed
* function fragment program
*/
GLboolean
_swrast_use_fragment_program(struct gl_context *ctx)
{
struct gl_program *fp = ctx->FragmentProgram._Current;
return fp && !(fp == ctx->FragmentProgram._TexEnvProgram
&& fp->arb.NumInstructions == 0);
}
/**
* Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel'
* and return results in 'colorOut'.
*/
static inline void
swizzle_texel(const GLfloat texel[4], GLfloat colorOut[4], GLuint swizzle)
{
if (swizzle == SWIZZLE_NOOP) {
COPY_4V(colorOut, texel);
}
else {
GLfloat vector[6];
vector[SWIZZLE_X] = texel[0];
vector[SWIZZLE_Y] = texel[1];
vector[SWIZZLE_Z] = texel[2];
vector[SWIZZLE_W] = texel[3];
vector[SWIZZLE_ZERO] = 0.0F;
vector[SWIZZLE_ONE] = 1.0F;
colorOut[0] = vector[GET_SWZ(swizzle, 0)];
colorOut[1] = vector[GET_SWZ(swizzle, 1)];
colorOut[2] = vector[GET_SWZ(swizzle, 2)];
colorOut[3] = vector[GET_SWZ(swizzle, 3)];
}
}
/**
* Fetch a texel with given lod.
* Called via machine->FetchTexelLod()
*/
static void
fetch_texel_lod( struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda,
GLuint unit, GLfloat color[4] )
{
const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
if (texObj) {
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLfloat rgba[4];
const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
lambda = CLAMP(lambda, samp->Attrib.MinLod, samp->Attrib.MaxLod);
swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
1, (const GLfloat (*)[4]) texcoord,
&lambda, &rgba);
swizzle_texel(rgba, color, texObj->Attrib._Swizzle);
}
else {
ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
}
}
/**
* Fetch a texel with the given partial derivatives to compute a level
* of detail in the mipmap.
* Called via machine->FetchTexelDeriv()
* \param lodBias the lod bias which may be specified by a TXB instruction,
* otherwise zero.
*/
static void
fetch_texel_deriv( struct gl_context *ctx, const GLfloat texcoord[4],
const GLfloat texdx[4], const GLfloat texdy[4],
GLfloat lodBias, GLuint unit, GLfloat color[4] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
const struct gl_texture_object *texObj = texUnit->_Current;
if (texObj) {
const struct gl_texture_image *texImg = _mesa_base_tex_image(texObj);
const struct swrast_texture_image *swImg =
swrast_texture_image_const(texImg);
const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
const GLfloat texW = (GLfloat) swImg->WidthScale;
const GLfloat texH = (GLfloat) swImg->HeightScale;
GLfloat lambda;
GLfloat rgba[4];
lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
texdx[1], texdy[1], /* dt/dx, dt/dy */
texdx[3], texdy[3], /* dq/dx, dq/dy */
texW, texH,
texcoord[0], texcoord[1], texcoord[3],
1.0F / texcoord[3]);
lambda += lodBias + texUnit->LodBias + samp->Attrib.LodBias;
lambda = CLAMP(lambda, samp->Attrib.MinLod, samp->Attrib.MaxLod);
swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
1, (const GLfloat (*)[4]) texcoord,
&lambda, &rgba);
swizzle_texel(rgba, color, texObj->Attrib._Swizzle);
}
else {
ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
}
}
/**
* Initialize the virtual fragment program machine state prior to running
* fragment program on a fragment. This involves initializing the input
* registers, condition codes, etc.
* \param machine the virtual machine state to init
* \param program the fragment program we're about to run
* \param span the span of pixels we'll operate on
* \param col which element (column) of the span we'll operate on
*/
static void
init_machine(struct gl_context *ctx, struct gl_program_machine *machine,
const struct gl_program *program, const SWspan *span, GLuint col)
{
GLfloat *wpos = span->array->attribs[VARYING_SLOT_POS][col];
/* ARB_fragment_coord_conventions */
if (program->info.fs.origin_upper_left)
wpos[1] = ctx->DrawBuffer->Height - 1 - wpos[1];
if (!program->info.fs.pixel_center_integer) {
wpos[0] += 0.5F;
wpos[1] += 0.5F;
}
/* Setup pointer to input attributes */
machine->Attribs = span->array->attribs;
machine->DerivX = (GLfloat (*)[4]) span->attrStepX;
machine->DerivY = (GLfloat (*)[4]) span->attrStepY;
machine->NumDeriv = VARYING_SLOT_MAX;
machine->Samplers = program->SamplerUnits;
/* if running a GLSL program (not ARB_fragment_program) */
if (ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
/* Store front/back facing value */
machine->Attribs[VARYING_SLOT_FACE][col][0] = 1.0F - span->facing;
}
machine->CurElement = col;
/* init call stack */
machine->StackDepth = 0;
machine->FetchTexelLod = fetch_texel_lod;
machine->FetchTexelDeriv = fetch_texel_deriv;
}
/**
* Run fragment program on the pixels in span from 'start' to 'end' - 1.
*/
static void
run_program(struct gl_context *ctx, SWspan *span, GLuint start, GLuint end)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const struct gl_program *program = ctx->FragmentProgram._Current;
const GLbitfield64 outputsWritten = program->info.outputs_written;
struct gl_program_machine *machine = &swrast->FragProgMachine;
GLuint i;
for (i = start; i < end; i++) {
if (span->array->mask[i]) {
init_machine(ctx, machine, program, span, i);
if (_mesa_execute_program(ctx, program, machine)) {
/* Store result color */
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
COPY_4V(span->array->attribs[VARYING_SLOT_COL0][i],
machine->Outputs[FRAG_RESULT_COLOR]);
}
else {
/* Multiple drawbuffers / render targets
* Note that colors beyond 0 and 1 will overwrite other
* attributes, such as FOGC, TEX0, TEX1, etc. That's OK.
*/
GLuint buf;
for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DATA0 + buf)) {
COPY_4V(span->array->attribs[VARYING_SLOT_COL0 + buf][i],
machine->Outputs[FRAG_RESULT_DATA0 + buf]);
}
}
}
/* Store result depth/z */
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPTH][2];
if (depth <= 0.0F)
span->array->z[i] = 0;
else if (depth >= 1.0F)
span->array->z[i] = ctx->DrawBuffer->_DepthMax;
else
span->array->z[i] =
(GLuint) (depth * ctx->DrawBuffer->_DepthMaxF + 0.5F);
}
}
else {
/* killed fragment */
span->array->mask[i] = GL_FALSE;
span->writeAll = GL_FALSE;
}
}
}
}
/**
* Execute the current fragment program for all the fragments
* in the given span.
*/
void
_swrast_exec_fragment_program( struct gl_context *ctx, SWspan *span )
{
const struct gl_program *program = ctx->FragmentProgram._Current;
/* incoming colors should be floats */
if (program->info.inputs_read & VARYING_BIT_COL0) {
assert(span->array->ChanType == GL_FLOAT);
}
run_program(ctx, span, 0, span->end);
if (program->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
span->interpMask &= ~SPAN_RGBA;
span->arrayMask |= SPAN_RGBA;
}
if (program->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
span->interpMask &= ~SPAN_Z;
span->arrayMask |= SPAN_Z;
}
}

View File

@ -1,42 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_FRAGPROG_H
#define S_FRAGPROG_H
#include "s_span.h"
struct gl_context;
GLboolean
_swrast_use_fragment_program(struct gl_context *ctx);
extern void
_swrast_exec_fragment_program(struct gl_context *ctx, SWspan *span);
#endif /* S_FRAGPROG_H */

View File

@ -1,267 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "s_aaline.h"
#include "s_context.h"
#include "s_feedback.h"
#include "s_lines.h"
#include "s_span.h"
/*
* Init the mask[] array to implement a line stipple.
*/
static void
compute_stipple_mask( struct gl_context *ctx, GLuint len, GLubyte mask[] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLuint i;
for (i = 0; i < len; i++) {
GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
if ((1 << bit) & ctx->Line.StipplePattern) {
mask[i] = GL_TRUE;
}
else {
mask[i] = GL_FALSE;
}
swrast->StippleCounter++;
}
}
/*
* To draw a wide line we can simply redraw the span N times, side by side.
*/
static void
draw_wide_line( struct gl_context *ctx, SWspan *span, GLboolean xMajor )
{
const GLint width = (GLint) CLAMP(ctx->Line.Width,
ctx->Const.MinLineWidth,
ctx->Const.MaxLineWidth);
GLint start;
assert(span->end < SWRAST_MAX_WIDTH);
if (width & 1)
start = width / 2;
else
start = width / 2 - 1;
if (xMajor) {
GLint *y = span->array->y;
GLuint i;
GLint w;
for (w = 0; w < width; w++) {
if (w == 0) {
for (i = 0; i < span->end; i++)
y[i] -= start;
}
else {
for (i = 0; i < span->end; i++)
y[i]++;
}
_swrast_write_rgba_span(ctx, span);
}
}
else {
GLint *x = span->array->x;
GLuint i;
GLint w;
for (w = 0; w < width; w++) {
if (w == 0) {
for (i = 0; i < span->end; i++)
x[i] -= start;
}
else {
for (i = 0; i < span->end; i++)
x[i]++;
}
_swrast_write_rgba_span(ctx, span);
}
}
}
/**********************************************************************/
/***** Rasterization *****/
/**********************************************************************/
/* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
#define NAME simple_no_z_rgba_line
#define INTERP_RGBA
#define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span);
#include "s_linetemp.h"
/* Z, fog, wide, stipple RGBA line */
#define NAME rgba_line
#define INTERP_RGBA
#define INTERP_Z
#define RENDER_SPAN(span) \
if (ctx->Line.StippleFlag) { \
span.arrayMask |= SPAN_MASK; \
compute_stipple_mask(ctx, span.end, span.array->mask); \
} \
if (ctx->Line.Width > 1.0) { \
draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
} \
else { \
_swrast_write_rgba_span(ctx, &span); \
}
#include "s_linetemp.h"
/* General-purpose line (any/all features). */
#define NAME general_line
#define INTERP_RGBA
#define INTERP_Z
#define INTERP_ATTRIBS
#define RENDER_SPAN(span) \
if (ctx->Line.StippleFlag) { \
span.arrayMask |= SPAN_MASK; \
compute_stipple_mask(ctx, span.end, span.array->mask); \
} \
if (ctx->Line.Width > 1.0) { \
draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
} \
else { \
_swrast_write_rgba_span(ctx, &span); \
}
#include "s_linetemp.h"
void
_swrast_add_spec_terms_line(struct gl_context *ctx,
const SWvertex *v0, const SWvertex *v1)
{
SWvertex *ncv0 = (SWvertex *)v0;
SWvertex *ncv1 = (SWvertex *)v1;
GLfloat rSum, gSum, bSum;
GLchan cSave[2][4];
/* save original colors */
COPY_CHAN4(cSave[0], ncv0->color);
COPY_CHAN4(cSave[1], ncv1->color);
/* sum v0 */
rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[VARYING_SLOT_COL1][0];
gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[VARYING_SLOT_COL1][1];
bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[VARYING_SLOT_COL1][2];
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
/* sum v1 */
rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[VARYING_SLOT_COL1][0];
gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[VARYING_SLOT_COL1][1];
bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[VARYING_SLOT_COL1][2];
UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum);
UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum);
UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum);
/* draw */
SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
/* restore original colors */
COPY_CHAN4(ncv0->color, cSave[0]);
COPY_CHAN4(ncv1->color, cSave[1]);
}
#ifdef DEBUG
/* record the current line function name */
static const char *lineFuncName = NULL;
#define USE(lineFunc) \
do { \
lineFuncName = #lineFunc; \
/*printf("%s\n", lineFuncName);*/ \
swrast->Line = lineFunc; \
} while (0)
#else
#define USE(lineFunc) swrast->Line = lineFunc
#endif
/**
* Determine which line drawing function to use given the current
* rendering context.
*
* Please update the summary flag _SWRAST_NEW_LINE if you add or remove
* tests to this code.
*/
void
_swrast_choose_line( struct gl_context *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLboolean specular = (ctx->Fog.ColorSumEnabled ||
(ctx->Light.Enabled &&
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR));
if (ctx->RenderMode == GL_RENDER) {
if (ctx->Line.SmoothFlag) {
/* antialiased lines */
_swrast_choose_aa_line_function(ctx);
assert(swrast->Line);
}
else if (ctx->Texture._EnabledCoordUnits
|| _swrast_use_fragment_program(ctx)
|| swrast->_FogEnabled
|| specular) {
USE(general_line);
}
else if (ctx->Depth.Test
|| ctx->Line.Width != 1.0F
|| ctx->Line.StippleFlag) {
/* no texture, but Z, fog, width>1, stipple, etc. */
#if CHAN_BITS == 32
USE(general_line);
#else
USE(rgba_line);
#endif
}
else {
assert(!ctx->Depth.Test);
assert(ctx->Line.Width == 1.0F);
/* simple lines */
USE(simple_no_z_rgba_line);
}
}
else if (ctx->RenderMode == GL_FEEDBACK) {
USE(_swrast_feedback_line);
}
else {
assert(ctx->RenderMode == GL_SELECT);
USE(_swrast_select_line);
}
}

View File

@ -1,41 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_LINES_H
#define S_LINES_H
#include "swrast.h"
void
_swrast_choose_line( struct gl_context *ctx );
void
_swrast_add_spec_terms_line( struct gl_context *ctx,
const SWvertex *v0,
const SWvertex *v1 );
#endif

View File

@ -1,402 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Line Rasterizer Template
*
* This file is #include'd to generate custom line rasterizers.
*
* The following macros may be defined to indicate what auxillary information
* must be interplated along the line:
* INTERP_Z - if defined, interpolate Z values
* INTERP_ATTRIBS - if defined, interpolate attribs (texcoords, varying, etc)
*
* When one can directly address pixels in the color buffer the following
* macros can be defined and used to directly compute pixel addresses during
* rasterization (see pixelPtr):
* PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
* BYTES_PER_ROW - number of bytes per row in the color buffer
* PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
* Y==0 at bottom of screen and increases upward.
*
* Similarly, for direct depth buffer access, this type is used for depth
* buffer addressing:
* DEPTH_TYPE - either GLushort or GLuint
*
* Optionally, one may provide one-time setup code
* SETUP_CODE - code which is to be executed once per line
*
* To actually "plot" each pixel the PLOT macro must be defined...
* PLOT(X,Y) - code to plot a pixel. Example:
* if (Z < *zPtr) {
* *zPtr = Z;
* color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
* FixedToInt(b0) );
* put_pixel( X, Y, color );
* }
*
* This code was designed for the origin to be in the lower-left corner.
*
*/
static void
NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 )
{
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
SWspan span;
GLuint interpFlags = 0;
GLint x0 = (GLint) vert0->attrib[VARYING_SLOT_POS][0];
GLint x1 = (GLint) vert1->attrib[VARYING_SLOT_POS][0];
GLint y0 = (GLint) vert0->attrib[VARYING_SLOT_POS][1];
GLint y1 = (GLint) vert1->attrib[VARYING_SLOT_POS][1];
GLint dx, dy;
GLint numPixels;
GLint xstep, ystep;
#if defined(DEPTH_TYPE)
const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
#define FixedToDepth(F) ((F) >> fixedToDepthShift)
GLint zPtrXstep, zPtrYstep;
DEPTH_TYPE *zPtr;
#elif defined(INTERP_Z)
const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
#endif
#ifdef PIXEL_ADDRESS
PIXEL_TYPE *pixelPtr;
GLint pixelXstep, pixelYstep;
#endif
#ifdef SETUP_CODE
SETUP_CODE
#endif
(void) swrast;
/* Cull primitives with malformed coordinates.
*/
{
GLfloat tmp = vert0->attrib[VARYING_SLOT_POS][0] + vert0->attrib[VARYING_SLOT_POS][1]
+ vert1->attrib[VARYING_SLOT_POS][0] + vert1->attrib[VARYING_SLOT_POS][1];
if (util_is_inf_or_nan(tmp))
return;
}
/*
printf("%s():\n", __func__);
printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
vert0->attrib[VARYING_SLOT_POS][0],
vert0->attrib[VARYING_SLOT_POS][1],
vert0->attrib[VARYING_SLOT_POS][2],
vert1->attrib[VARYING_SLOT_POS][0],
vert1->attrib[VARYING_SLOT_POS][1],
vert1->attrib[VARYING_SLOT_POS][2]);
printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
vert0->color[0], vert0->color[1], vert0->color[2],
vert1->color[0], vert1->color[1], vert1->color[2]);
printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
vert0->specular[0], vert0->specular[1], vert0->specular[2],
vert1->specular[0], vert1->specular[1], vert1->specular[2]);
*/
/*
* Despite being clipped to the view volume, the line's window coordinates
* may just lie outside the window bounds. That is, if the legal window
* coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
* This quick and dirty code nudges the endpoints inside the window if
* necessary.
*/
#ifdef CLIP_HACK
{
GLint w = ctx->DrawBuffer->Width;
GLint h = ctx->DrawBuffer->Height;
if ((x0==w) | (x1==w)) {
if ((x0==w) & (x1==w))
return;
x0 -= x0==w;
x1 -= x1==w;
}
if ((y0==h) | (y1==h)) {
if ((y0==h) & (y1==h))
return;
y0 -= y0==h;
y1 -= y1==h;
}
}
#endif
dx = x1 - x0;
dy = y1 - y0;
if (dx == 0 && dy == 0)
return;
/*
printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __func__, dx, dy,
vert0->attrib[VARYING_SLOT_COL1][0],
vert0->attrib[VARYING_SLOT_COL1][1],
vert0->attrib[VARYING_SLOT_COL1][2],
vert0->attrib[VARYING_SLOT_COL1][3],
vert1->attrib[VARYING_SLOT_COL1][0],
vert1->attrib[VARYING_SLOT_COL1][1],
vert1->attrib[VARYING_SLOT_COL1][2],
vert1->attrib[VARYING_SLOT_COL1][3]);
*/
#ifdef DEPTH_TYPE
zPtr = (DEPTH_TYPE *) _swrast_pixel_address(zrb, x0, y0);
#endif
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
#endif
if (dx<0) {
dx = -dx; /* make positive */
xstep = -1;
#ifdef DEPTH_TYPE
zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
#endif
#ifdef PIXEL_ADDRESS
pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
#endif
}
else {
xstep = 1;
#ifdef DEPTH_TYPE
zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
#endif
#ifdef PIXEL_ADDRESS
pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
#endif
}
if (dy<0) {
dy = -dy; /* make positive */
ystep = -1;
#ifdef DEPTH_TYPE
zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
#endif
#ifdef PIXEL_ADDRESS
pixelYstep = BYTES_PER_ROW;
#endif
}
else {
ystep = 1;
#ifdef DEPTH_TYPE
zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
#endif
#ifdef PIXEL_ADDRESS
pixelYstep = -(BYTES_PER_ROW);
#endif
}
assert(dx >= 0);
assert(dy >= 0);
numPixels = MAX2(dx, dy);
/*
* Span setup: compute start and step values for all interpolated values.
*/
interpFlags |= SPAN_RGBA;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
span.red = ChanToFixed(vert0->color[0]);
span.green = ChanToFixed(vert0->color[1]);
span.blue = ChanToFixed(vert0->color[2]);
span.alpha = ChanToFixed(vert0->color[3]);
span.redStep = (ChanToFixed(vert1->color[0]) - span.red ) / numPixels;
span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels;
span.blueStep = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels;
span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels;
}
else {
span.red = ChanToFixed(vert1->color[0]);
span.green = ChanToFixed(vert1->color[1]);
span.blue = ChanToFixed(vert1->color[2]);
span.alpha = ChanToFixed(vert1->color[3]);
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
span.alphaStep = 0;
}
#if defined(INTERP_Z) || defined(DEPTH_TYPE)
interpFlags |= SPAN_Z;
{
if (depthBits <= 16) {
span.z = FloatToFixed(vert0->attrib[VARYING_SLOT_POS][2]) + FIXED_HALF;
span.zStep = FloatToFixed( vert1->attrib[VARYING_SLOT_POS][2]
- vert0->attrib[VARYING_SLOT_POS][2]) / numPixels;
}
else {
/* don't use fixed point */
span.z = (GLuint) vert0->attrib[VARYING_SLOT_POS][2];
span.zStep = (GLint) (( vert1->attrib[VARYING_SLOT_POS][2]
- vert0->attrib[VARYING_SLOT_POS][2]) / numPixels);
}
}
#endif
#if defined(INTERP_ATTRIBS)
{
const GLfloat invLen = 1.0F / numPixels;
const GLfloat invw0 = vert0->attrib[VARYING_SLOT_POS][3];
const GLfloat invw1 = vert1->attrib[VARYING_SLOT_POS][3];
span.attrStart[VARYING_SLOT_POS][3] = invw0;
span.attrStepX[VARYING_SLOT_POS][3] = (invw1 - invw0) * invLen;
span.attrStepY[VARYING_SLOT_POS][3] = 0.0;
ATTRIB_LOOP_BEGIN
if (swrast->_InterpMode[attr] == GL_FLAT) {
COPY_4V(span.attrStart[attr], vert1->attrib[attr]);
ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
}
else {
GLuint c;
for (c = 0; c < 4; c++) {
float da;
span.attrStart[attr][c] = invw0 * vert0->attrib[attr][c];
da = (invw1 * vert1->attrib[attr][c]) - span.attrStart[attr][c];
span.attrStepX[attr][c] = da * invLen;
}
}
ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
ATTRIB_LOOP_END
}
#endif
INIT_SPAN(span, GL_LINE);
span.end = numPixels;
span.interpMask = interpFlags;
span.arrayMask = SPAN_XY;
span.facing = swrast->PointLineFacing;
/*
* Draw
*/
if (dx > dy) {
/*** X-major line ***/
GLint i;
GLint errorInc = dy+dy;
GLint error = errorInc-dx;
GLint errorDec = error-dx;
for (i = 0; i < dx; i++) {
#ifdef DEPTH_TYPE
GLuint Z = FixedToDepth(span.z);
#endif
#ifdef PLOT
PLOT( x0, y0 );
#else
span.array->x[i] = x0;
span.array->y[i] = y0;
#endif
x0 += xstep;
#ifdef DEPTH_TYPE
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
span.z += span.zStep;
#endif
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
#endif
if (error < 0) {
error += errorInc;
}
else {
error += errorDec;
y0 += ystep;
#ifdef DEPTH_TYPE
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
#endif
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
#endif
}
}
}
else {
/*** Y-major line ***/
GLint i;
GLint errorInc = dx+dx;
GLint error = errorInc-dy;
GLint errorDec = error-dy;
for (i=0;i<dy;i++) {
#ifdef DEPTH_TYPE
GLuint Z = FixedToDepth(span.z);
#endif
#ifdef PLOT
PLOT( x0, y0 );
#else
span.array->x[i] = x0;
span.array->y[i] = y0;
#endif
y0 += ystep;
#ifdef DEPTH_TYPE
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
span.z += span.zStep;
#endif
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
#endif
if (error<0) {
error += errorInc;
}
else {
error += errorDec;
x0 += xstep;
#ifdef DEPTH_TYPE
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
#endif
#ifdef PIXEL_ADDRESS
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
#endif
}
}
}
#ifdef RENDER_SPAN
RENDER_SPAN( span );
#endif
(void)span;
}
#undef NAME
#undef INTERP_Z
#undef INTERP_ATTRIBS
#undef PIXEL_ADDRESS
#undef PIXEL_TYPE
#undef DEPTH_TYPE
#undef BYTES_PER_ROW
#undef SETUP_CODE
#undef PLOT
#undef CLIP_HACK
#undef FixedToDepth
#undef RENDER_SPAN

View File

@ -1,218 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "s_context.h"
#include "s_logic.h"
#include "s_span.h"
/**
* We do all logic ops on 4-byte GLuints.
* Depending on bytes per pixel, the mask array elements correspond to
* 1, 2 or 4 GLuints.
*/
#define LOGIC_OP_LOOP(MODE, MASKSTRIDE) \
do { \
GLuint i; \
switch (MODE) { \
case GL_CLEAR: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = 0; \
} \
} \
break; \
case GL_SET: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = ~0; \
} \
} \
break; \
case GL_COPY: \
/* do nothing */ \
break; \
case GL_COPY_INVERTED: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = ~src[i]; \
} \
} \
break; \
case GL_NOOP: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = dest[i]; \
} \
} \
break; \
case GL_INVERT: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = ~dest[i]; \
} \
} \
break; \
case GL_AND: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] &= dest[i]; \
} \
} \
break; \
case GL_NAND: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = ~(src[i] & dest[i]); \
} \
} \
break; \
case GL_OR: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] |= dest[i]; \
} \
} \
break; \
case GL_NOR: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = ~(src[i] | dest[i]); \
} \
} \
break; \
case GL_XOR: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] ^= dest[i]; \
} \
} \
break; \
case GL_EQUIV: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = ~(src[i] ^ dest[i]); \
} \
} \
break; \
case GL_AND_REVERSE: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = src[i] & ~dest[i]; \
} \
} \
break; \
case GL_AND_INVERTED: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = ~src[i] & dest[i]; \
} \
} \
break; \
case GL_OR_REVERSE: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = src[i] | ~dest[i]; \
} \
} \
break; \
case GL_OR_INVERTED: \
for (i = 0; i < n; i++) { \
if (mask[i / MASKSTRIDE]) { \
src[i] = ~src[i] | dest[i]; \
} \
} \
break; \
default: \
_mesa_problem(ctx, "bad logicop mode");\
} \
} while (0)
static inline void
logicop_uint1(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[],
const GLubyte mask[])
{
LOGIC_OP_LOOP(ctx->Color.LogicOp, 1);
}
static inline void
logicop_uint2(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[],
const GLubyte mask[])
{
LOGIC_OP_LOOP(ctx->Color.LogicOp, 2);
}
static inline void
logicop_uint4(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[],
const GLubyte mask[])
{
LOGIC_OP_LOOP(ctx->Color.LogicOp, 4);
}
/**
* Apply the current logic operator to a span of RGBA pixels.
* We can handle horizontal runs of pixels (spans) or arrays of x/y
* pixel coordinates.
*/
void
_swrast_logicop_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
SWspan *span)
{
void *rbPixels;
assert(span->end < SWRAST_MAX_WIDTH);
assert(span->arrayMask & SPAN_RGBA);
rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
/* treat 4*GLubyte as GLuint */
logicop_uint1(ctx, span->end,
(GLuint *) span->array->rgba8,
(const GLuint *) rbPixels, span->array->mask);
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
/* treat 2*GLushort as GLuint */
logicop_uint2(ctx, 2 * span->end,
(GLuint *) span->array->rgba16,
(const GLuint *) rbPixels, span->array->mask);
}
else {
logicop_uint4(ctx, 4 * span->end,
(GLuint *) span->array->attribs[VARYING_SLOT_COL0],
(const GLuint *) rbPixels, span->array->mask);
}
}

View File

@ -1,40 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_LOGIC_H
#define S_LOGIC_H
#include "s_span.h"
struct gl_context;
struct gl_renderbuffer;
extern void
_swrast_logicop_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
SWspan *span);
#endif

View File

@ -1,108 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Implement the effect of glColorMask and glIndexMask in software.
*/
#include "main/glheader.h"
#include "main/macros.h"
#include "s_context.h"
#include "s_masking.h"
#include "s_span.h"
/**
* Apply the color mask to a span of rgba values.
*/
void
_swrast_mask_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
SWspan *span, GLuint buf)
{
const GLuint n = span->end;
void *rbPixels;
assert(n < SWRAST_MAX_WIDTH);
assert(span->arrayMask & SPAN_RGBA);
rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
/*
* Do component masking.
* Note that we're not using span->array->mask[] here. We could...
*/
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
const GLubyte colormask[4] = {
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xff : 0,
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xff : 0,
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xff : 0,
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xff : 0,
};
GLuint srcMask;
memcpy(&srcMask, colormask, sizeof(srcMask));
const GLuint dstMask = ~srcMask;
const GLuint *dst = (const GLuint *) rbPixels;
GLuint *src = (GLuint *) span->array->rgba8;
GLuint i;
for (i = 0; i < n; i++) {
src[i] = (src[i] & srcMask) | (dst[i] & dstMask);
}
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
/* 2-byte components */
/* XXX try to use 64-bit arithmetic someday */
const GLushort rMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xffff : 0x0;
const GLushort gMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xffff : 0x0;
const GLushort bMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xffff : 0x0;
const GLushort aMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xffff : 0x0;
const GLushort (*dst)[4] = (const GLushort (*)[4]) rbPixels;
GLushort (*src)[4] = span->array->rgba16;
GLuint i;
for (i = 0; i < n; i++) {
src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
}
}
else {
/* 4-byte components */
const GLuint rMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? ~0x0 : 0x0;
const GLuint gMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? ~0x0 : 0x0;
const GLuint bMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? ~0x0 : 0x0;
const GLuint aMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? ~0x0 : 0x0;
const GLuint (*dst)[4] = (const GLuint (*)[4]) rbPixels;
GLuint (*src)[4] = (GLuint (*)[4]) span->array->attribs[VARYING_SLOT_COL0];
GLuint i;
for (i = 0; i < n; i++) {
src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
}
}
}

View File

@ -1,41 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_MASKING_H
#define S_MASKING_H
#include "main/glheader.h"
#include "s_span.h"
struct gl_context;
struct gl_renderbuffer;
extern void
_swrast_mask_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
SWspan *span, GLuint buf);
#endif

View File

@ -1,564 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/framebuffer.h"
#include "main/glheader.h"
#include "main/macros.h"
#include "s_context.h"
#include "s_feedback.h"
#include "s_points.h"
#include "s_span.h"
/**
* Used to cull points with invalid coords
*/
#define CULL_INVALID(V) \
do { \
float tmp = (V)->attrib[VARYING_SLOT_POS][0] \
+ (V)->attrib[VARYING_SLOT_POS][1]; \
if (util_is_inf_or_nan(tmp)) \
return; \
} while(0)
/**
* Get/compute the point size.
* The size may come from a vertex shader, or computed with attentuation
* or just the glPointSize value.
* Must also clamp to user-defined range and implmentation limits.
*/
static inline GLfloat
get_size(const struct gl_context *ctx, const SWvertex *vert, GLboolean smoothed)
{
GLfloat size;
if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
/* use vertex's point size */
size = vert->pointSize;
}
else {
/* use constant point size */
size = ctx->Point.Size;
}
/* always clamp to user-specified limits */
size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
/* clamp to implementation limits */
if (smoothed)
size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);
else
size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
return size;
}
/**
* Draw a point sprite
*/
static void
sprite_point(struct gl_context *ctx, const SWvertex *vert)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
SWspan span;
GLfloat size;
GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1];
GLuint numTcoords = 0;
GLfloat t0, dtdy;
CULL_INVALID(vert);
/* z coord */
if (ctx->DrawBuffer->Visual.depthBits <= 16)
span.z = FloatToFixed(vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
else
span.z = (GLuint) (vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
span.zStep = 0;
size = get_size(ctx, vert, GL_FALSE);
/* span init */
INIT_SPAN(span, GL_POINT);
span.interpMask = SPAN_Z | SPAN_RGBA;
span.facing = swrast->PointLineFacing;
span.red = ChanToFixed(vert->color[0]);
span.green = ChanToFixed(vert->color[1]);
span.blue = ChanToFixed(vert->color[2]);
span.alpha = ChanToFixed(vert->color[3]);
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
span.alphaStep = 0;
/* need these for fragment programs */
span.attrStart[VARYING_SLOT_POS][3] = 1.0F;
span.attrStepX[VARYING_SLOT_POS][3] = 0.0F;
span.attrStepY[VARYING_SLOT_POS][3] = 0.0F;
{
GLfloat s, dsdx;
/* texcoord / pointcoord interpolants */
s = 0.0F;
dsdx = 1.0F / size;
if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) {
dtdy = 1.0F / size;
t0 = 0.5F * dtdy;
}
else {
/* GL_UPPER_LEFT */
dtdy = -1.0F / size;
t0 = 1.0F + 0.5F * dtdy;
}
ATTRIB_LOOP_BEGIN
if (attr >= VARYING_SLOT_TEX0 && attr <= VARYING_SLOT_TEX7) {
/* a texcoord attribute */
const GLuint u = attr - VARYING_SLOT_TEX0;
assert(u < MAX_TEXTURE_COORD_UNITS);
if (ctx->Point.CoordReplace & (1u << u)) {
tCoords[numTcoords++] = attr;
span.attrStart[attr][0] = s;
span.attrStart[attr][1] = 0.0; /* overwritten below */
span.attrStart[attr][2] = 0.0;
span.attrStart[attr][3] = 1.0;
span.attrStepX[attr][0] = dsdx;
span.attrStepX[attr][1] = 0.0;
span.attrStepX[attr][2] = 0.0;
span.attrStepX[attr][3] = 0.0;
span.attrStepY[attr][0] = 0.0;
span.attrStepY[attr][1] = dtdy;
span.attrStepY[attr][2] = 0.0;
span.attrStepY[attr][3] = 0.0;
continue;
}
}
else if (attr == VARYING_SLOT_PNTC) {
/* GLSL gl_PointCoord.xy (.zw undefined) */
span.attrStart[VARYING_SLOT_PNTC][0] = 0.0;
span.attrStart[VARYING_SLOT_PNTC][1] = 0.0; /* t0 set below */
span.attrStepX[VARYING_SLOT_PNTC][0] = dsdx;
span.attrStepX[VARYING_SLOT_PNTC][1] = 0.0;
span.attrStepY[VARYING_SLOT_PNTC][0] = 0.0;
span.attrStepY[VARYING_SLOT_PNTC][1] = dtdy;
tCoords[numTcoords++] = VARYING_SLOT_PNTC;
continue;
}
/* use vertex's texcoord/attrib */
COPY_4V(span.attrStart[attr], vert->attrib[attr]);
ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
ATTRIB_LOOP_END;
}
/* compute pos, bounds and render */
{
const GLfloat x = vert->attrib[VARYING_SLOT_POS][0];
const GLfloat y = vert->attrib[VARYING_SLOT_POS][1];
GLint iSize = (GLint) (size + 0.5F);
GLint xmin, xmax, ymin, ymax, iy;
GLint iRadius;
GLfloat tcoord = t0;
iSize = MAX2(1, iSize);
iRadius = iSize / 2;
if (iSize & 1) {
/* odd size */
xmin = (GLint) (x - iRadius);
xmax = (GLint) (x + iRadius);
ymin = (GLint) (y - iRadius);
ymax = (GLint) (y + iRadius);
}
else {
/* even size */
/* 0.501 factor allows conformance to pass */
xmin = (GLint) (x + 0.501F) - iRadius;
xmax = xmin + iSize - 1;
ymin = (GLint) (y + 0.501F) - iRadius;
ymax = ymin + iSize - 1;
}
/* render spans */
for (iy = ymin; iy <= ymax; iy++) {
GLuint i;
/* setup texcoord T for this row */
for (i = 0; i < numTcoords; i++) {
span.attrStart[tCoords[i]][1] = tcoord;
}
/* these might get changed by span clipping */
span.x = xmin;
span.y = iy;
span.end = xmax - xmin + 1;
_swrast_write_rgba_span(ctx, &span);
tcoord += dtdy;
}
}
}
/**
* Draw smooth/antialiased point. RGB or CI mode.
*/
static void
smooth_point(struct gl_context *ctx, const SWvertex *vert)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
SWspan span;
GLfloat size, alphaAtten;
CULL_INVALID(vert);
/* z coord */
if (ctx->DrawBuffer->Visual.depthBits <= 16)
span.z = FloatToFixed(vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
else
span.z = (GLuint) (vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
span.zStep = 0;
size = get_size(ctx, vert, GL_TRUE);
/* alpha attenuation / fade factor */
if (_mesa_is_multisample_enabled(ctx)) {
if (vert->pointSize >= ctx->Point.Threshold) {
alphaAtten = 1.0F;
}
else {
GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
alphaAtten = dsize * dsize;
}
}
else {
alphaAtten = 1.0;
}
(void) alphaAtten; /* not used */
/* span init */
INIT_SPAN(span, GL_POINT);
span.interpMask = SPAN_Z | SPAN_RGBA;
span.arrayMask = SPAN_COVERAGE | SPAN_MASK;
span.facing = swrast->PointLineFacing;
span.red = ChanToFixed(vert->color[0]);
span.green = ChanToFixed(vert->color[1]);
span.blue = ChanToFixed(vert->color[2]);
span.alpha = ChanToFixed(vert->color[3]);
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
span.alphaStep = 0;
/* need these for fragment programs */
span.attrStart[VARYING_SLOT_POS][3] = 1.0F;
span.attrStepX[VARYING_SLOT_POS][3] = 0.0F;
span.attrStepY[VARYING_SLOT_POS][3] = 0.0F;
ATTRIB_LOOP_BEGIN
COPY_4V(span.attrStart[attr], vert->attrib[attr]);
ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
ATTRIB_LOOP_END
/* compute pos, bounds and render */
{
const GLfloat x = vert->attrib[VARYING_SLOT_POS][0];
const GLfloat y = vert->attrib[VARYING_SLOT_POS][1];
const GLfloat radius = 0.5F * size;
const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
const GLfloat rmax = radius + 0.7071F;
const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
const GLfloat rmax2 = rmax * rmax;
const GLfloat cscale = 1.0F / (rmax2 - rmin2);
const GLint xmin = (GLint) (x - radius);
const GLint xmax = (GLint) (x + radius);
const GLint ymin = (GLint) (y - radius);
const GLint ymax = (GLint) (y + radius);
GLint ix, iy;
for (iy = ymin; iy <= ymax; iy++) {
/* these might get changed by span clipping */
span.x = xmin;
span.y = iy;
span.end = xmax - xmin + 1;
/* compute coverage for each pixel in span */
for (ix = xmin; ix <= xmax; ix++) {
const GLfloat dx = ix - x + 0.5F;
const GLfloat dy = iy - y + 0.5F;
const GLfloat dist2 = dx * dx + dy * dy;
GLfloat coverage;
if (dist2 < rmax2) {
if (dist2 >= rmin2) {
/* compute partial coverage */
coverage = 1.0F - (dist2 - rmin2) * cscale;
}
else {
/* full coverage */
coverage = 1.0F;
}
span.array->mask[ix - xmin] = 1;
}
else {
/* zero coverage - fragment outside the radius */
coverage = 0.0;
span.array->mask[ix - xmin] = 0;
}
span.array->coverage[ix - xmin] = coverage;
}
/* render span */
_swrast_write_rgba_span(ctx, &span);
}
}
}
/**
* Draw large (size >= 1) non-AA point. RGB or CI mode.
*/
static void
large_point(struct gl_context *ctx, const SWvertex *vert)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
SWspan span;
GLfloat size;
CULL_INVALID(vert);
/* z coord */
if (ctx->DrawBuffer->Visual.depthBits <= 16)
span.z = FloatToFixed(vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
else
span.z = (GLuint) (vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
span.zStep = 0;
size = get_size(ctx, vert, GL_FALSE);
/* span init */
INIT_SPAN(span, GL_POINT);
span.arrayMask = SPAN_XY;
span.facing = swrast->PointLineFacing;
span.interpMask = SPAN_Z | SPAN_RGBA;
span.red = ChanToFixed(vert->color[0]);
span.green = ChanToFixed(vert->color[1]);
span.blue = ChanToFixed(vert->color[2]);
span.alpha = ChanToFixed(vert->color[3]);
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
span.alphaStep = 0;
/* need these for fragment programs */
span.attrStart[VARYING_SLOT_POS][3] = 1.0F;
span.attrStepX[VARYING_SLOT_POS][3] = 0.0F;
span.attrStepY[VARYING_SLOT_POS][3] = 0.0F;
ATTRIB_LOOP_BEGIN
COPY_4V(span.attrStart[attr], vert->attrib[attr]);
ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
ATTRIB_LOOP_END
/* compute pos, bounds and render */
{
const GLfloat x = vert->attrib[VARYING_SLOT_POS][0];
const GLfloat y = vert->attrib[VARYING_SLOT_POS][1];
GLint iSize = (GLint) (size + 0.5F);
GLint xmin, xmax, ymin, ymax, ix, iy;
GLint iRadius;
iSize = MAX2(1, iSize);
iRadius = iSize / 2;
if (iSize & 1) {
/* odd size */
xmin = (GLint) (x - iRadius);
xmax = (GLint) (x + iRadius);
ymin = (GLint) (y - iRadius);
ymax = (GLint) (y + iRadius);
}
else {
/* even size */
/* 0.501 factor allows conformance to pass */
xmin = (GLint) (x + 0.501F) - iRadius;
xmax = xmin + iSize - 1;
ymin = (GLint) (y + 0.501F) - iRadius;
ymax = ymin + iSize - 1;
}
/* generate fragments */
span.end = 0;
for (iy = ymin; iy <= ymax; iy++) {
for (ix = xmin; ix <= xmax; ix++) {
span.array->x[span.end] = ix;
span.array->y[span.end] = iy;
span.end++;
}
}
assert(span.end <= SWRAST_MAX_WIDTH);
_swrast_write_rgba_span(ctx, &span);
}
}
/**
* Draw size=1, single-pixel point
*/
static void
pixel_point(struct gl_context *ctx, const SWvertex *vert)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
/*
* Note that unlike the other functions, we put single-pixel points
* into a special span array in order to render as many points as
* possible with a single _swrast_write_rgba_span() call.
*/
SWspan *span = &(swrast->PointSpan);
GLuint count;
CULL_INVALID(vert);
/* Span init */
span->interpMask = 0;
span->arrayMask = SPAN_XY | SPAN_Z;
span->arrayMask |= SPAN_RGBA;
/*span->arrayMask |= SPAN_LAMBDA;*/
span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */
/* need these for fragment programs */
span->attrStart[VARYING_SLOT_POS][3] = 1.0F;
span->attrStepX[VARYING_SLOT_POS][3] = 0.0F;
span->attrStepY[VARYING_SLOT_POS][3] = 0.0F;
/* check if we need to flush */
if (span->end >= SWRAST_MAX_WIDTH ||
(swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) ||
span->facing != swrast->PointLineFacing) {
if (span->end > 0) {
_swrast_write_rgba_span(ctx, span);
span->end = 0;
}
}
count = span->end;
span->facing = swrast->PointLineFacing;
/* fragment attributes */
span->array->rgba[count][RCOMP] = vert->color[0];
span->array->rgba[count][GCOMP] = vert->color[1];
span->array->rgba[count][BCOMP] = vert->color[2];
span->array->rgba[count][ACOMP] = vert->color[3];
ATTRIB_LOOP_BEGIN
COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]);
ATTRIB_LOOP_END
/* fragment position */
span->array->x[count] = (GLint) vert->attrib[VARYING_SLOT_POS][0];
span->array->y[count] = (GLint) vert->attrib[VARYING_SLOT_POS][1];
span->array->z[count] = (GLint) (vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
span->end = count + 1;
assert(span->end <= SWRAST_MAX_WIDTH);
}
/**
* Add specular color to primary color, draw point, restore original
* primary color.
*/
void
_swrast_add_spec_terms_point(struct gl_context *ctx, const SWvertex *v0)
{
SWvertex *ncv0 = (SWvertex *) v0; /* cast away const */
GLfloat rSum, gSum, bSum;
GLchan cSave[4];
/* save */
COPY_CHAN4(cSave, ncv0->color);
/* sum */
rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[VARYING_SLOT_COL1][0];
gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[VARYING_SLOT_COL1][1];
bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[VARYING_SLOT_COL1][2];
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
/* draw */
SWRAST_CONTEXT(ctx)->SpecPoint(ctx, ncv0);
/* restore */
COPY_CHAN4(ncv0->color, cSave);
}
/**
* Examine current state to determine which point drawing function to use.
*/
void
_swrast_choose_point(struct gl_context *ctx)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLfloat size = CLAMP(ctx->Point.Size,
ctx->Point.MinSize,
ctx->Point.MaxSize);
if (ctx->RenderMode == GL_RENDER) {
if (ctx->Point.PointSprite) {
swrast->Point = sprite_point;
}
else if (ctx->Point.SmoothFlag) {
swrast->Point = smooth_point;
}
else if (size > 1.0F ||
ctx->Point._Attenuated ||
ctx->VertexProgram.PointSizeEnabled) {
swrast->Point = large_point;
}
else {
swrast->Point = pixel_point;
}
}
else if (ctx->RenderMode == GL_FEEDBACK) {
swrast->Point = _swrast_feedback_point;
}
else {
/* GL_SELECT mode */
swrast->Point = _swrast_select_point;
}
}

View File

@ -1,39 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_POINTS_H
#define S_POINTS_H
#include "swrast.h"
extern void
_swrast_choose_point( struct gl_context *ctx );
extern void
_swrast_add_spec_terms_point( struct gl_context *ctx,
const SWvertex *v0 );
#endif

View File

@ -1,642 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Functions for allocating/managing software-based renderbuffers.
* Also, routines for reading/writing software-based renderbuffer data as
* ubytes, ushorts, uints, etc.
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/fbobject.h"
#include "main/formats.h"
#include "main/mtypes.h"
#include "main/renderbuffer.h"
#include "util/u_memory.h"
#include "swrast/s_context.h"
#include "swrast/s_renderbuffer.h"
/**
* This is a software fallback for the gl_renderbuffer->AllocStorage
* function.
* Device drivers will typically override this function for the buffers
* which it manages (typically color buffers, Z and stencil).
* Other buffers (like software accumulation and aux buffers) which the driver
* doesn't manage can be handled with this function.
*
* This one multi-purpose function can allocate stencil, depth, accum, color
* or color-index buffers!
*/
static GLboolean
soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
GLuint bpp;
switch (internalFormat) {
case GL_RGB:
case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
rb->Format = MESA_FORMAT_BGR_UNORM8;
break;
case GL_RGBA:
case GL_RGBA2:
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
#if UTIL_ARCH_LITTLE_ENDIAN
rb->Format = MESA_FORMAT_R8G8B8A8_UNORM;
#else
rb->Format = MESA_FORMAT_A8B8G8R8_UNORM;
#endif
break;
case GL_RGBA16:
case GL_RGBA16_SNORM:
/* for accum buffer */
rb->Format = MESA_FORMAT_RGBA_SNORM16;
break;
case GL_STENCIL_INDEX:
case GL_STENCIL_INDEX1_EXT:
case GL_STENCIL_INDEX4_EXT:
case GL_STENCIL_INDEX8_EXT:
case GL_STENCIL_INDEX16_EXT:
rb->Format = MESA_FORMAT_S_UINT8;
break;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
rb->Format = MESA_FORMAT_Z_UNORM16;
break;
case GL_DEPTH_COMPONENT24:
rb->Format = MESA_FORMAT_Z24_UNORM_X8_UINT;
break;
case GL_DEPTH_COMPONENT32:
rb->Format = MESA_FORMAT_Z_UNORM32;
break;
case GL_DEPTH_STENCIL_EXT:
case GL_DEPTH24_STENCIL8_EXT:
rb->Format = MESA_FORMAT_S8_UINT_Z24_UNORM;
break;
default:
/* unsupported format */
return GL_FALSE;
}
bpp = _mesa_get_format_bytes(rb->Format);
/* free old buffer storage */
free(srb->Buffer);
srb->Buffer = NULL;
srb->RowStride = width * bpp;
if (width > 0 && height > 0) {
/* allocate new buffer storage */
srb->Buffer = malloc(srb->RowStride * height);
if (srb->Buffer == NULL) {
rb->Width = 0;
rb->Height = 0;
_mesa_error(ctx, GL_OUT_OF_MEMORY,
"software renderbuffer allocation (%d x %d x %d)",
width, height, bpp);
return GL_FALSE;
}
}
rb->Width = width;
rb->Height = height;
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
if (rb->Name == 0 &&
internalFormat == GL_RGBA16_SNORM &&
rb->_BaseFormat == 0) {
/* NOTE: This is a special case just for accumulation buffers.
* This is a very limited use case- there's no snorm texturing or
* rendering going on.
*/
rb->_BaseFormat = GL_RGBA;
}
else {
/* the internalFormat should have been error checked long ago */
assert(rb->_BaseFormat);
}
return GL_TRUE;
}
/**
* Called via gl_renderbuffer::Delete()
*/
static void
soft_renderbuffer_delete(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
free(srb->Buffer);
srb->Buffer = NULL;
_mesa_delete_renderbuffer(ctx, rb);
}
void
_swrast_map_soft_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer *rb,
GLuint x, GLuint y, GLuint w, GLuint h,
GLbitfield mode,
GLubyte **out_map,
GLint *out_stride,
bool flip_y)
{
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
GLubyte *map = srb->Buffer;
int cpp = _mesa_get_format_bytes(rb->Format);
int stride = rb->Width * cpp;
if (!map) {
*out_map = NULL;
*out_stride = 0;
}
map += y * stride;
map += x * cpp;
*out_map = map;
*out_stride = stride;
}
void
_swrast_unmap_soft_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer *rb)
{
}
/**
* Allocate a software-based renderbuffer. This is called via the
* ctx->Driver.NewRenderbuffer() function when the user creates a new
* renderbuffer.
* This would not be used for hardware-based renderbuffers.
*/
struct gl_renderbuffer *
_swrast_new_soft_renderbuffer(struct gl_context *ctx, GLuint name)
{
struct swrast_renderbuffer *srb = CALLOC_STRUCT(swrast_renderbuffer);
if (srb) {
_mesa_init_renderbuffer(&srb->Base, name);
srb->Base.AllocStorage = soft_renderbuffer_storage;
srb->Base.Delete = soft_renderbuffer_delete;
}
return &srb->Base;
}
/**
* Add software-based color renderbuffers to the given framebuffer.
* This is a helper routine for device drivers when creating a
* window system framebuffer (not a user-created render/framebuffer).
* Once this function is called, you can basically forget about this
* renderbuffer; core Mesa will handle all the buffer management and
* rendering!
*/
static GLboolean
add_color_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
GLuint rgbBits, GLuint alphaBits,
GLboolean frontLeft, GLboolean backLeft,
GLboolean frontRight, GLboolean backRight)
{
gl_buffer_index b;
if (rgbBits > 16 || alphaBits > 16) {
_mesa_problem(ctx,
"Unsupported bit depth in add_color_renderbuffers");
return GL_FALSE;
}
assert(MAX_COLOR_ATTACHMENTS >= 4);
for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
struct gl_renderbuffer *rb;
if (b == BUFFER_FRONT_LEFT && !frontLeft)
continue;
else if (b == BUFFER_BACK_LEFT && !backLeft)
continue;
else if (b == BUFFER_FRONT_RIGHT && !frontRight)
continue;
else if (b == BUFFER_BACK_RIGHT && !backRight)
continue;
assert(fb->Attachment[b].Renderbuffer == NULL);
rb = ctx->Driver.NewRenderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
return GL_FALSE;
}
rb->InternalFormat = GL_RGBA;
rb->AllocStorage = soft_renderbuffer_storage;
_mesa_attach_and_own_rb(fb, b, rb);
}
return GL_TRUE;
}
/**
* Add a software-based depth renderbuffer to the given framebuffer.
* This is a helper routine for device drivers when creating a
* window system framebuffer (not a user-created render/framebuffer).
* Once this function is called, you can basically forget about this
* renderbuffer; core Mesa will handle all the buffer management and
* rendering!
*/
static GLboolean
add_depth_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
GLuint depthBits)
{
struct gl_renderbuffer *rb;
if (depthBits > 32) {
_mesa_problem(ctx,
"Unsupported depthBits in add_depth_renderbuffer");
return GL_FALSE;
}
assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
rb = _swrast_new_soft_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
return GL_FALSE;
}
if (depthBits <= 16) {
rb->InternalFormat = GL_DEPTH_COMPONENT16;
}
else if (depthBits <= 24) {
rb->InternalFormat = GL_DEPTH_COMPONENT24;
}
else {
rb->InternalFormat = GL_DEPTH_COMPONENT32;
}
rb->AllocStorage = soft_renderbuffer_storage;
_mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
return GL_TRUE;
}
/**
* Add a software-based stencil renderbuffer to the given framebuffer.
* This is a helper routine for device drivers when creating a
* window system framebuffer (not a user-created render/framebuffer).
* Once this function is called, you can basically forget about this
* renderbuffer; core Mesa will handle all the buffer management and
* rendering!
*/
static GLboolean
add_stencil_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
GLuint stencilBits)
{
struct gl_renderbuffer *rb;
if (stencilBits > 16) {
_mesa_problem(ctx,
"Unsupported stencilBits in add_stencil_renderbuffer");
return GL_FALSE;
}
assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
rb = _swrast_new_soft_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
return GL_FALSE;
}
assert(stencilBits <= 8);
rb->InternalFormat = GL_STENCIL_INDEX8;
rb->AllocStorage = soft_renderbuffer_storage;
_mesa_attach_and_own_rb(fb, BUFFER_STENCIL, rb);
return GL_TRUE;
}
static GLboolean
add_depth_stencil_renderbuffer(struct gl_context *ctx,
struct gl_framebuffer *fb)
{
struct gl_renderbuffer *rb;
assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
rb = _swrast_new_soft_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth+stencil buffer");
return GL_FALSE;
}
rb->InternalFormat = GL_DEPTH_STENCIL;
rb->AllocStorage = soft_renderbuffer_storage;
_mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
_mesa_attach_and_reference_rb(fb, BUFFER_STENCIL, rb);
return GL_TRUE;
}
/**
* Add a software-based accumulation renderbuffer to the given framebuffer.
* This is a helper routine for device drivers when creating a
* window system framebuffer (not a user-created render/framebuffer).
* Once this function is called, you can basically forget about this
* renderbuffer; core Mesa will handle all the buffer management and
* rendering!
*/
static GLboolean
add_accum_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
GLuint redBits, GLuint greenBits,
GLuint blueBits, GLuint alphaBits)
{
struct gl_renderbuffer *rb;
if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
_mesa_problem(ctx,
"Unsupported accumBits in add_accum_renderbuffer");
return GL_FALSE;
}
assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
rb = _swrast_new_soft_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
return GL_FALSE;
}
rb->InternalFormat = GL_RGBA16_SNORM;
rb->AllocStorage = soft_renderbuffer_storage;
_mesa_attach_and_own_rb(fb, BUFFER_ACCUM, rb);
return GL_TRUE;
}
/**
* Create/attach software-based renderbuffers to the given framebuffer.
* This is a helper routine for device drivers. Drivers can just as well
* call the individual _mesa_add_*_renderbuffer() routines directly.
*/
void
_swrast_add_soft_renderbuffers(struct gl_framebuffer *fb,
GLboolean color,
GLboolean depth,
GLboolean stencil,
GLboolean accum,
GLboolean alpha)
{
GLboolean frontLeft = GL_TRUE;
GLboolean backLeft = fb->Visual.doubleBufferMode;
GLboolean frontRight = fb->Visual.stereoMode;
GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
if (color) {
assert(fb->Visual.redBits == fb->Visual.greenBits);
assert(fb->Visual.redBits == fb->Visual.blueBits);
add_color_renderbuffers(NULL, fb,
fb->Visual.redBits,
fb->Visual.alphaBits,
frontLeft, backLeft,
frontRight, backRight);
}
#if 0
/* This is pretty much for debugging purposes only since there's a perf
* hit for using combined depth/stencil in swrast.
*/
if (depth && fb->Visual.depthBits == 24 &&
stencil && fb->Visual.stencilBits == 8) {
/* use combined depth/stencil buffer */
add_depth_stencil_renderbuffer(NULL, fb);
}
else
#else
(void) add_depth_stencil_renderbuffer;
#endif
{
if (depth) {
assert(fb->Visual.depthBits > 0);
add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
}
if (stencil) {
assert(fb->Visual.stencilBits > 0);
add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
}
}
if (accum) {
assert(fb->Visual.accumRedBits > 0);
assert(fb->Visual.accumGreenBits > 0);
assert(fb->Visual.accumBlueBits > 0);
add_accum_renderbuffer(NULL, fb,
fb->Visual.accumRedBits,
fb->Visual.accumGreenBits,
fb->Visual.accumBlueBits,
fb->Visual.accumAlphaBits);
}
}
static void
map_attachment(struct gl_context *ctx,
struct gl_framebuffer *fb,
gl_buffer_index buffer)
{
struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
if (texObj) {
/* map texture image (render to texture) */
const GLuint level = fb->Attachment[buffer].TextureLevel;
const GLuint face = fb->Attachment[buffer].CubeMapFace;
const GLuint slice = fb->Attachment[buffer].Zoffset;
struct gl_texture_image *texImage = texObj->Image[face][level];
if (texImage) {
ctx->Driver.MapTextureImage(ctx, texImage, slice,
0, 0, texImage->Width, texImage->Height,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
&srb->Map, &srb->RowStride);
}
}
else if (rb) {
/* Map ordinary renderbuffer */
ctx->Driver.MapRenderbuffer(ctx, rb,
0, 0, rb->Width, rb->Height,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
&srb->Map, &srb->RowStride,
fb->FlipY);
}
assert(srb->Map);
}
static void
unmap_attachment(struct gl_context *ctx,
struct gl_framebuffer *fb,
gl_buffer_index buffer)
{
struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
if (texObj) {
/* unmap texture image (render to texture) */
const GLuint level = fb->Attachment[buffer].TextureLevel;
const GLuint face = fb->Attachment[buffer].CubeMapFace;
const GLuint slice = fb->Attachment[buffer].Zoffset;
struct gl_texture_image *texImage = texObj->Image[face][level];
if (texImage) {
ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
}
}
else if (rb) {
/* unmap ordinary renderbuffer */
ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
srb->Map = NULL;
}
/**
* Determine what type to use (ubyte vs. float) for span colors for the
* given renderbuffer.
* See also _swrast_write_rgba_span().
*/
static void
find_renderbuffer_colortype(struct gl_renderbuffer *rb)
{
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
GLuint rbMaxBits = _mesa_get_format_max_bits(rb->Format);
GLenum rbDatatype = _mesa_get_format_datatype(rb->Format);
if (rbDatatype == GL_UNSIGNED_NORMALIZED && rbMaxBits <= 8) {
/* the buffer's values fit in GLubyte values */
srb->ColorType = GL_UNSIGNED_BYTE;
}
else {
/* use floats otherwise */
srb->ColorType = GL_FLOAT;
}
}
/**
* Map the renderbuffers we'll use for tri/line/point rendering.
*/
void
_swrast_map_renderbuffers(struct gl_context *ctx)
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct gl_renderbuffer *depthRb, *stencilRb;
GLuint buf;
depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
if (depthRb) {
/* map depth buffer */
map_attachment(ctx, fb, BUFFER_DEPTH);
}
stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
if (stencilRb && stencilRb != depthRb) {
/* map stencil buffer */
map_attachment(ctx, fb, BUFFER_STENCIL);
}
for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
if (fb->_ColorDrawBufferIndexes[buf] != BUFFER_NONE) {
map_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]);
find_renderbuffer_colortype(fb->_ColorDrawBuffers[buf]);
}
}
}
/**
* Unmap renderbuffers after rendering.
*/
void
_swrast_unmap_renderbuffers(struct gl_context *ctx)
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct gl_renderbuffer *depthRb, *stencilRb;
GLuint buf;
depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
if (depthRb) {
/* map depth buffer */
unmap_attachment(ctx, fb, BUFFER_DEPTH);
}
stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
if (stencilRb && stencilRb != depthRb) {
/* map stencil buffer */
unmap_attachment(ctx, fb, BUFFER_STENCIL);
}
for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
if (fb->_ColorDrawBufferIndexes[buf] != BUFFER_NONE) {
unmap_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]);
}
}
}

View File

@ -1,66 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_RENDERBUFFER_H
#define S_RENDERBUFFER_H
#include "main/glheader.h"
struct gl_context;
struct gl_framebuffer;
struct gl_renderbuffer;
extern struct gl_renderbuffer *
_swrast_new_soft_renderbuffer(struct gl_context *ctx, GLuint name);
extern void
_swrast_map_soft_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer *rb,
GLuint x, GLuint y, GLuint w, GLuint h,
GLbitfield mode,
GLubyte **out_map,
GLint *out_stride,
bool flip_y);
extern void
_swrast_unmap_soft_renderbuffer(struct gl_context *ctx,
struct gl_renderbuffer *rb);
extern void
_swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb);
extern void
_swrast_add_soft_renderbuffers(struct gl_framebuffer *fb,
GLboolean color,
GLboolean depth,
GLboolean stencil,
GLboolean accum,
GLboolean alpha);
#endif /* S_RENDERBUFFER_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,217 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_SPAN_H
#define S_SPAN_H
#include "main/config.h"
#include "main/glheader.h"
#include "main/mtypes.h"
#include "swrast/s_chan.h"
#include "swrast/swrast.h"
struct gl_context;
struct gl_renderbuffer;
/**
* \defgroup SpanFlags
* Special bitflags to describe span data.
*
* In general, the point/line/triangle functions interpolate/emit the
* attributes specified by swrast->_ActiveAttribs (i.e. FRAT_BIT_* values).
* Some things don't fit into that, though, so we have these flags.
*/
/*@{*/
#define SPAN_RGBA 0x01 /**< interpMask and arrayMask */
#define SPAN_Z 0x02 /**< interpMask and arrayMask */
#define SPAN_FLAT 0x04 /**< interpMask: flat shading? */
#define SPAN_XY 0x08 /**< array.x[], y[] valid? */
#define SPAN_MASK 0x10 /**< was array.mask[] filled in by caller? */
#define SPAN_LAMBDA 0x20 /**< array.lambda[] valid? */
#define SPAN_COVERAGE 0x40 /**< array.coverage[] valid? */
/*@}*/
/**
* \sw_span_arrays
* \brief Arrays of fragment values.
*
* These will either be computed from the span x/xStep values or
* filled in by glDraw/CopyPixels, etc.
* These arrays are separated out of sw_span to conserve memory.
*/
typedef struct sw_span_arrays
{
/** Per-fragment attributes (indexed by VARYING_SLOT_* tokens) */
/* XXX someday look at transposing first two indexes for better memory
* access pattern.
*/
GLfloat attribs[VARYING_SLOT_MAX][SWRAST_MAX_WIDTH][4];
/** This mask indicates which fragments are alive or culled */
GLubyte mask[SWRAST_MAX_WIDTH];
GLenum ChanType; /**< Color channel type, GL_UNSIGNED_BYTE, GL_FLOAT */
/** Attribute arrays that don't fit into attribs[] array above */
/*@{*/
GLubyte rgba8[SWRAST_MAX_WIDTH][4];
GLushort rgba16[SWRAST_MAX_WIDTH][4];
GLchan (*rgba)[4]; /** either == rgba8 or rgba16 */
GLint x[SWRAST_MAX_WIDTH]; /**< fragment X coords */
GLint y[SWRAST_MAX_WIDTH]; /**< fragment Y coords */
GLuint z[SWRAST_MAX_WIDTH]; /**< fragment Z coords */
GLuint index[SWRAST_MAX_WIDTH]; /**< Color indexes */
GLfloat lambda[MAX_TEXTURE_COORD_UNITS][SWRAST_MAX_WIDTH]; /**< Texture LOD */
GLfloat coverage[SWRAST_MAX_WIDTH]; /**< Fragment coverage for AA/smoothing */
/*@}*/
} SWspanarrays;
/**
* The SWspan structure describes the colors, Z, fogcoord, texcoords,
* etc for either a horizontal run or an array of independent pixels.
* We can either specify a base/step to indicate interpolated values, or
* fill in explicit arrays of values. The interpMask and arrayMask bitfields
* indicate which attributes are active interpolants or arrays, respectively.
*
* It would be interesting to experiment with multiprocessor rasterization
* with this structure. The triangle rasterizer could simply emit a
* stream of these structures which would be consumed by one or more
* span-processing threads which could run in parallel.
*/
typedef struct sw_span
{
/** Coord of first fragment in horizontal span/run */
GLint x, y;
/** Number of fragments in the span */
GLuint end;
/** for clipping left edge of spans */
GLuint leftClip;
/** This flag indicates that mask[] array is effectively filled with ones */
GLboolean writeAll;
/** either GL_POLYGON, GL_LINE, GL_POLYGON, GL_BITMAP */
GLenum primitive;
/** 0 = front-facing span, 1 = back-facing span (for two-sided stencil) */
GLuint facing;
/**
* This bitmask (of \link SpanFlags SPAN_* flags\endlink) indicates
* which of the attrStart/StepX/StepY variables are relevant.
*/
GLbitfield interpMask;
/** Fragment attribute interpolants */
GLfloat attrStart[VARYING_SLOT_MAX][4]; /**< initial value */
GLfloat attrStepX[VARYING_SLOT_MAX][4]; /**< dvalue/dx */
GLfloat attrStepY[VARYING_SLOT_MAX][4]; /**< dvalue/dy */
/* XXX the rest of these will go away eventually... */
/* For horizontal spans, step is the partial derivative wrt X.
* For lines, step is the delta from one fragment to the next.
*/
GLfixed red, redStep;
GLfixed green, greenStep;
GLfixed blue, blueStep;
GLfixed alpha, alphaStep;
GLfixed index, indexStep;
GLfixed z, zStep; /**< XXX z should probably be GLuint */
GLfixed intTex[2], intTexStep[2]; /**< (s,t) for unit[0] only */
/**
* This bitmask (of \link SpanFlags SPAN_* flags\endlink) indicates
* which of the fragment arrays in the span_arrays struct are relevant.
*/
GLbitfield arrayMask;
/** Mask of VARYING_BIT_x bits */
GLbitfield64 arrayAttribs;
/**
* We store the arrays of fragment values in a separate struct so
* that we can allocate sw_span structs on the stack without using
* a lot of memory. The span_arrays struct is about 1.4MB while the
* sw_span struct is only about 512 bytes.
*/
SWspanarrays *array;
} SWspan;
#define INIT_SPAN(S, PRIMITIVE) \
do { \
(S).primitive = (PRIMITIVE); \
(S).interpMask = 0x0; \
(S).arrayMask = 0x0; \
(S).arrayAttribs = 0x0; \
(S).end = 0; \
(S).leftClip = 0; \
(S).facing = 0; \
(S).array = SWRAST_CONTEXT(ctx)->SpanArrays; \
} while (0)
extern void
_swrast_span_default_attribs(struct gl_context *ctx, SWspan *span);
extern void
_swrast_span_interpolate_z( const struct gl_context *ctx, SWspan *span );
extern GLfloat
_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
GLfloat s, GLfloat t, GLfloat q, GLfloat invQ);
extern void
_swrast_write_rgba_span( struct gl_context *ctx, SWspan *span);
extern void
_swrast_read_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLuint n, GLint x, GLint y, GLvoid *rgba);
extern void
_swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLenum datatype,
GLuint count, GLint x, GLint y,
const void *values, const GLubyte *mask);
extern void *
_swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
SWspan *span);
#endif

View File

@ -1,710 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/format_pack.h"
#include "main/format_unpack.h"
#include "main/stencil.h"
#include "s_context.h"
#include "s_depth.h"
#include "s_stencil.h"
#include "s_span.h"
/* Stencil Logic:
IF stencil test fails THEN
Apply fail-op to stencil value
Don't write the pixel (RGBA,Z)
ELSE
IF doing depth test && depth test fails THEN
Apply zfail-op to stencil value
Write RGBA and Z to appropriate buffers
ELSE
Apply zpass-op to stencil value
ENDIF
*/
/**
* Compute/return the offset of the stencil value in a pixel.
* For example, if the format is Z24+S8, the position of the stencil bits
* within the 4-byte pixel will be either 0 or 3.
*/
static GLint
get_stencil_offset(mesa_format format)
{
const GLubyte one = 1;
GLubyte pixel[MAX_PIXEL_BYTES];
GLint bpp = _mesa_get_format_bytes(format);
GLint i;
assert(_mesa_get_format_bits(format, GL_STENCIL_BITS) == 8);
memset(pixel, 0, sizeof(pixel));
_mesa_pack_ubyte_stencil_row(format, 1, &one, pixel);
for (i = 0; i < bpp; i++) {
if (pixel[i])
return i;
}
_mesa_problem(NULL, "get_stencil_offset() failed\n");
return 0;
}
/** Clamp the stencil value to [0, 255] */
static inline GLubyte
clamp(GLint val)
{
if (val < 0)
return 0;
else if (val > 255)
return 255;
else
return val;
}
#define STENCIL_OP(NEW_VAL) \
if (invmask == 0) { \
for (i = j = 0; i < n; i++, j += stride) { \
if (mask[i]) { \
GLubyte s = stencil[j]; \
(void) s; \
stencil[j] = (GLubyte) (NEW_VAL); \
} \
} \
} \
else { \
for (i = j = 0; i < n; i++, j += stride) { \
if (mask[i]) { \
GLubyte s = stencil[j]; \
stencil[j] = (GLubyte) ((invmask & s) | (wrtmask & (NEW_VAL))); \
} \
} \
}
/**
* Apply the given stencil operator to the array of stencil values.
* Don't touch stencil[i] if mask[i] is zero.
* @param n number of stencil values
* @param oper the stencil buffer operator
* @param face 0 or 1 for front or back face operation
* @param stencil array of stencil values (in/out)
* @param mask array [n] of flag: 1=apply operator, 0=don't apply operator
* @param stride stride between stencil values
*/
static void
apply_stencil_op(const struct gl_context *ctx, GLenum oper, GLuint face,
GLuint n, GLubyte stencil[], const GLubyte mask[],
GLint stride)
{
const GLubyte ref = _mesa_get_stencil_ref(ctx, face);
const GLubyte wrtmask = ctx->Stencil.WriteMask[face];
const GLubyte invmask = (GLubyte) (~wrtmask);
GLuint i, j;
switch (oper) {
case GL_KEEP:
/* do nothing */
break;
case GL_ZERO:
/* replace stencil buf values with zero */
STENCIL_OP(0);
break;
case GL_REPLACE:
/* replace stencil buf values with ref value */
STENCIL_OP(ref);
break;
case GL_INCR:
/* increment stencil buf values, with clamping */
STENCIL_OP(clamp(s + 1));
break;
case GL_DECR:
/* increment stencil buf values, with clamping */
STENCIL_OP(clamp(s - 1));
break;
case GL_INCR_WRAP_EXT:
/* increment stencil buf values, without clamping */
STENCIL_OP(s + 1);
break;
case GL_DECR_WRAP_EXT:
/* increment stencil buf values, without clamping */
STENCIL_OP(s - 1);
break;
case GL_INVERT:
/* replace stencil buf values with inverted value */
STENCIL_OP(~s);
break;
default:
_mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
}
}
#define STENCIL_TEST(FUNC) \
for (i = j = 0; i < n; i++, j += stride) { \
if (mask[i]) { \
s = (GLubyte) (stencil[j] & valueMask); \
if (FUNC) { \
/* stencil pass */ \
fail[i] = 0; \
} \
else { \
/* stencil fail */ \
fail[i] = 1; \
mask[i] = 0; \
} \
} \
else { \
fail[i] = 0; \
} \
}
/**
* Apply stencil test to an array of stencil values (before depth buffering).
* For the values that fail, we'll apply the GL_STENCIL_FAIL operator to
* the stencil values.
*
* @param face 0 or 1 for front or back-face polygons
* @param n number of pixels in the array
* @param stencil array of [n] stencil values (in/out)
* @param mask array [n] of flag: 0=skip the pixel, 1=stencil the pixel,
* values are set to zero where the stencil test fails.
* @param stride stride between stencil values
* @return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
*/
static GLboolean
do_stencil_test(struct gl_context *ctx, GLuint face, GLuint n,
GLubyte stencil[], GLubyte mask[], GLint stride)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLubyte *fail = swrast->stencil_temp.buf2;
GLboolean allfail = GL_FALSE;
GLuint i, j;
const GLuint valueMask = ctx->Stencil.ValueMask[face];
const GLubyte ref = (GLubyte) (_mesa_get_stencil_ref(ctx, face) & valueMask);
GLubyte s;
/*
* Perform stencil test. The results of this operation are stored
* in the fail[] array:
* IF fail[i] is non-zero THEN
* the stencil fail operator is to be applied
* ELSE
* the stencil fail operator is not to be applied
* ENDIF
*/
switch (ctx->Stencil.Function[face]) {
case GL_NEVER:
STENCIL_TEST(0);
allfail = GL_TRUE;
break;
case GL_LESS:
STENCIL_TEST(ref < s);
break;
case GL_LEQUAL:
STENCIL_TEST(ref <= s);
break;
case GL_GREATER:
STENCIL_TEST(ref > s);
break;
case GL_GEQUAL:
STENCIL_TEST(ref >= s);
break;
case GL_EQUAL:
STENCIL_TEST(ref == s);
break;
case GL_NOTEQUAL:
STENCIL_TEST(ref != s);
break;
case GL_ALWAYS:
STENCIL_TEST(1);
break;
default:
_mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
return 0;
}
if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
apply_stencil_op(ctx, ctx->Stencil.FailFunc[face], face, n, stencil,
fail, stride);
}
return !allfail;
}
/**
* Compute the zpass/zfail masks by comparing the pre- and post-depth test
* masks.
*/
static inline void
compute_pass_fail_masks(GLuint n, const GLubyte origMask[],
const GLubyte newMask[],
GLubyte passMask[], GLubyte failMask[])
{
GLuint i;
for (i = 0; i < n; i++) {
assert(newMask[i] == 0 || newMask[i] == 1);
passMask[i] = origMask[i] & newMask[i];
failMask[i] = origMask[i] & (newMask[i] ^ 1);
}
}
/**
* Get 8-bit stencil values from random locations in the stencil buffer.
*/
static void
get_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLuint count, const GLint x[], const GLint y[],
GLubyte stencil[])
{
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
const GLint w = rb->Width, h = rb->Height;
const GLubyte *map = _swrast_pixel_address(rb, 0, 0);
GLuint i;
if (rb->Format == MESA_FORMAT_S_UINT8) {
const GLint rowStride = srb->RowStride;
for (i = 0; i < count; i++) {
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
stencil[i] = *(map + y[i] * rowStride + x[i]);
}
}
}
else {
const GLint bpp = _mesa_get_format_bytes(rb->Format);
const GLint rowStride = srb->RowStride;
for (i = 0; i < count; i++) {
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
const GLubyte *src = map + y[i] * rowStride + x[i] * bpp;
_mesa_unpack_ubyte_stencil_row(rb->Format, 1, src, &stencil[i]);
}
}
}
}
/**
** Pack ubyte stencil pixels
**/
static void
pack_ubyte_stencil_Z24_S8(const uint8_t *src, void *dst)
{
/* don't disturb the Z values */
uint32_t *d = ((uint32_t *) dst);
uint32_t s = *src;
uint32_t z = *d & 0xffffff00;
*d = z | s;
}
static void
pack_ubyte_stencil_S8_Z24(const uint8_t *src, void *dst)
{
/* don't disturb the Z values */
uint32_t *d = ((uint32_t *) dst);
uint32_t s = *src << 24;
uint32_t z = *d & 0xffffff;
*d = s | z;
}
static void
pack_ubyte_stencil_S8(const uint8_t *src, void *dst)
{
uint8_t *d = (uint8_t *) dst;
*d = *src;
}
static void
pack_ubyte_stencil_Z32_FLOAT_X24S8(const uint8_t *src, void *dst)
{
float *d = ((float *) dst);
d[1] = *src;
}
/** Pack a uint8_t stencil value to dest address */
typedef void (*mesa_pack_ubyte_stencil_func)(const uint8_t *src, void *dst);
static mesa_pack_ubyte_stencil_func
get_pack_ubyte_stencil_func(mesa_format format)
{
switch (format) {
case MESA_FORMAT_S8_UINT_Z24_UNORM:
return pack_ubyte_stencil_Z24_S8;
case MESA_FORMAT_Z24_UNORM_S8_UINT:
return pack_ubyte_stencil_S8_Z24;
case MESA_FORMAT_S_UINT8:
return pack_ubyte_stencil_S8;
case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
return pack_ubyte_stencil_Z32_FLOAT_X24S8;
default:
unreachable("unexpected format in get_pack_ubyte_stencil_func()");
}
}
/**
* Put 8-bit stencil values at random locations into the stencil buffer.
*/
static void
put_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLuint count, const GLint x[], const GLint y[],
const GLubyte stencil[])
{
const GLint w = rb->Width, h = rb->Height;
mesa_pack_ubyte_stencil_func pack_stencil =
get_pack_ubyte_stencil_func(rb->Format);
GLuint i;
for (i = 0; i < count; i++) {
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
pack_stencil(&stencil[i], dst);
}
}
}
/**
* /return GL_TRUE = one or more fragments passed,
* GL_FALSE = all fragments failed.
*/
GLboolean
_swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
const GLint stencilOffset = get_stencil_offset(rb->Format);
const GLint stencilStride = _mesa_get_format_bytes(rb->Format);
const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
const GLuint count = span->end;
GLubyte *mask = span->array->mask;
GLubyte *stencilTemp = swrast->stencil_temp.buf1;
GLubyte *stencilBuf;
if (span->arrayMask & SPAN_XY) {
/* read stencil values from random locations */
get_s8_values(ctx, rb, count, span->array->x, span->array->y,
stencilTemp);
stencilBuf = stencilTemp;
}
else {
/* Processing a horizontal run of pixels. Since stencil is always
* 8 bits for all MESA_FORMATs, we just need to use the right offset
* and stride to access them.
*/
stencilBuf = _swrast_pixel_address(rb, span->x, span->y) + stencilOffset;
}
/*
* Apply the stencil test to the fragments.
* failMask[i] is 1 if the stencil test failed.
*/
if (!do_stencil_test(ctx, face, count, stencilBuf, mask, stencilStride)) {
/* all fragments failed the stencil test, we're done. */
span->writeAll = GL_FALSE;
if (span->arrayMask & SPAN_XY) {
/* need to write the updated stencil values back to the buffer */
put_s8_values(ctx, rb, count, span->array->x, span->array->y,
stencilTemp);
}
return GL_FALSE;
}
/*
* Some fragments passed the stencil test, apply depth test to them
* and apply Zpass and Zfail stencil ops.
*/
if (ctx->Depth.Test == GL_FALSE ||
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer == NULL) {
/*
* No depth buffer, just apply zpass stencil function to active pixels.
*/
apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, count,
stencilBuf, mask, stencilStride);
}
else {
/*
* Perform depth buffering, then apply zpass or zfail stencil function.
*/
SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLubyte *passMask = swrast->stencil_temp.buf2;
GLubyte *failMask = swrast->stencil_temp.buf3;
GLubyte *origMask = swrast->stencil_temp.buf4;
/* save the current mask bits */
memcpy(origMask, mask, count * sizeof(GLubyte));
/* apply the depth test */
_swrast_depth_test_span(ctx, span);
compute_pass_fail_masks(count, origMask, mask, passMask, failMask);
/* apply the pass and fail operations */
if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
count, stencilBuf, failMask, stencilStride);
}
if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
count, stencilBuf, passMask, stencilStride);
}
}
/* Write updated stencil values back into hardware stencil buffer */
if (span->arrayMask & SPAN_XY) {
put_s8_values(ctx, rb, count, span->array->x, span->array->y,
stencilBuf);
}
span->writeAll = GL_FALSE;
return GL_TRUE; /* one or more fragments passed both tests */
}
/**
* Return a span of stencil values from the stencil buffer.
* Used for glRead/CopyPixels
* Input: n - how many pixels
* x,y - location of first pixel
* Output: stencil - the array of stencil values
*/
void
_swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLint n, GLint x, GLint y, GLubyte stencil[])
{
GLubyte *src;
if (y < 0 || y >= (GLint) rb->Height ||
x + n <= 0 || x >= (GLint) rb->Width) {
/* span is completely outside framebuffer */
return; /* undefined values OK */
}
if (x < 0) {
GLint dx = -x;
x = 0;
n -= dx;
stencil += dx;
}
if (x + n > (GLint) rb->Width) {
GLint dx = x + n - rb->Width;
n -= dx;
}
if (n <= 0) {
return;
}
src = _swrast_pixel_address(rb, x, y);
_mesa_unpack_ubyte_stencil_row(rb->Format, n, src, stencil);
}
/**
* Write a span of stencil values to the stencil buffer. This function
* applies the stencil write mask when needed.
* Used for glDraw/CopyPixels
* Input: n - how many pixels
* x, y - location of first pixel
* stencil - the array of stencil values
*/
void
_swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y,
const GLubyte stencil[] )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
const GLuint stencilMask = ctx->Stencil.WriteMask[0];
GLubyte *stencilBuf;
if (y < 0 || y >= (GLint) rb->Height ||
x + n <= 0 || x >= (GLint) rb->Width) {
/* span is completely outside framebuffer */
return; /* undefined values OK */
}
if (x < 0) {
GLint dx = -x;
x = 0;
n -= dx;
stencil += dx;
}
if (x + n > (GLint) rb->Width) {
GLint dx = x + n - rb->Width;
n -= dx;
}
if (n <= 0) {
return;
}
stencilBuf = _swrast_pixel_address(rb, x, y);
if ((stencilMask & stencilMax) != stencilMax) {
/* need to apply writemask */
GLubyte *destVals = swrast->stencil_temp.buf1;
GLubyte *newVals = swrast->stencil_temp.buf2;
GLint i;
_mesa_unpack_ubyte_stencil_row(rb->Format, n, stencilBuf, destVals);
for (i = 0; i < n; i++) {
newVals[i]
= (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
}
_mesa_pack_ubyte_stencil_row(rb->Format, n, newVals, stencilBuf);
}
else {
_mesa_pack_ubyte_stencil_row(rb->Format, n, stencil, stencilBuf);
}
}
/**
* Clear the stencil buffer. If the buffer is a combined
* depth+stencil buffer, only the stencil bits will be touched.
*/
void
_swrast_clear_stencil_buffer(struct gl_context *ctx)
{
struct gl_renderbuffer *rb =
ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
const GLuint writeMask = ctx->Stencil.WriteMask[0];
const GLuint stencilMax = (1 << stencilBits) - 1;
GLint x, y, width, height;
GLubyte *map;
GLint rowStride, i, j;
GLbitfield mapMode;
if (!rb || writeMask == 0)
return;
/* compute region to clear */
x = ctx->DrawBuffer->_Xmin;
y = ctx->DrawBuffer->_Ymin;
width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
mapMode = GL_MAP_WRITE_BIT;
if ((writeMask & stencilMax) != stencilMax) {
/* need to mask stencil values */
mapMode |= GL_MAP_READ_BIT;
}
else if (_mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) > 0) {
/* combined depth+stencil, need to mask Z values */
mapMode |= GL_MAP_READ_BIT;
}
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
mapMode, &map, &rowStride,
ctx->DrawBuffer->FlipY);
if (!map) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(stencil)");
return;
}
switch (rb->Format) {
case MESA_FORMAT_S_UINT8:
{
GLubyte clear = ctx->Stencil.Clear & writeMask & 0xff;
GLubyte mask = (~writeMask) & 0xff;
if (mask != 0) {
/* masked clear */
for (i = 0; i < height; i++) {
GLubyte *row = map;
for (j = 0; j < width; j++) {
row[j] = (row[j] & mask) | clear;
}
map += rowStride;
}
}
else if (rowStride == width) {
/* clear whole buffer */
memset(map, clear, width * height);
}
else {
/* clear scissored */
for (i = 0; i < height; i++) {
memset(map, clear, width);
map += rowStride;
}
}
}
break;
case MESA_FORMAT_Z24_UNORM_S8_UINT:
{
GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24;
GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff;
for (i = 0; i < height; i++) {
GLuint *row = (GLuint *) map;
for (j = 0; j < width; j++) {
row[j] = (row[j] & mask) | clear;
}
map += rowStride;
}
}
break;
case MESA_FORMAT_S8_UINT_Z24_UNORM:
{
GLuint clear = ctx->Stencil.Clear & writeMask & 0xff;
GLuint mask = 0xffffff00 | ((~writeMask) & 0xff);
for (i = 0; i < height; i++) {
GLuint *row = (GLuint *) map;
for (j = 0; j < width; j++) {
row[j] = (row[j] & mask) | clear;
}
map += rowStride;
}
}
break;
default:
_mesa_problem(ctx, "Unexpected stencil buffer format %s"
" in _swrast_clear_stencil_buffer()",
_mesa_get_format_name(rb->Format));
}
ctx->Driver.UnmapRenderbuffer(ctx, rb);
}

View File

@ -1,53 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_STENCIL_H
#define S_STENCIL_H
#include "main/mtypes.h"
#include "s_span.h"
extern GLboolean
_swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span);
extern void
_swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
GLint n, GLint x, GLint y, GLubyte stencil[]);
extern void
_swrast_write_stencil_span( struct gl_context *ctx, GLint n, GLint x, GLint y,
const GLubyte stencil[] );
extern void
_swrast_clear_stencil_buffer(struct gl_context *ctx);
#endif

View File

@ -1,721 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "main/pixeltransfer.h"
#include "main/samplerobj.h"
#include "program/prog_instruction.h"
#include "s_context.h"
#include "s_texcombine.h"
/**
* Pointer to array of float[4]
* This type makes the code below more concise and avoids a lot of casting.
*/
typedef float (*float4_array)[4];
/**
* Return array of texels for given unit.
*/
static inline float4_array
get_texel_array(SWcontext *swrast, GLuint unit)
{
#ifdef _OPENMP
return (float4_array) (swrast->TexelBuffer + unit * SWRAST_MAX_WIDTH * 4 * omp_get_num_threads() + (SWRAST_MAX_WIDTH * 4 * omp_get_thread_num()));
#else
return (float4_array) (swrast->TexelBuffer + unit * SWRAST_MAX_WIDTH * 4);
#endif
}
/**
* Do texture application for:
* GL_EXT_texture_env_combine
* GL_ARB_texture_env_combine
* GL_EXT_texture_env_dot3
* GL_ARB_texture_env_dot3
* GL_ATI_texture_env_combine3
* GL_NV_texture_env_combine4
* conventional GL texture env modes
*
* \param ctx rendering context
* \param unit the texture combiner unit
* \param primary_rgba incoming fragment color array
* \param texelBuffer pointer to texel colors for all texture units
*
* \param span two fields are used in this function:
* span->end: number of fragments to process
* span->array->rgba: incoming/result fragment colors
*/
static void
texture_combine( struct gl_context *ctx, GLuint unit,
const float4_array primary_rgba,
const GLfloat *texelBuffer,
SWspan *span )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const struct gl_fixedfunc_texture_unit *textureUnit =
&ctx->Texture.FixedFuncUnit[unit];
const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
float4_array argRGB[MAX_COMBINER_TERMS];
float4_array argA[MAX_COMBINER_TERMS];
const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
const GLuint numArgsRGB = combine->_NumArgsRGB;
const GLuint numArgsA = combine->_NumArgsA;
float4_array ccolor[4], rgba;
GLuint i, term;
GLuint n = span->end;
GLchan (*rgbaChan)[4] = span->array->rgba;
/* alloc temp pixel buffers */
rgba = malloc(4 * n * sizeof(GLfloat));
if (!rgba) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
return;
}
for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
ccolor[i] = malloc(4 * n * sizeof(GLfloat));
if (!ccolor[i]) {
while (i) {
free(ccolor[i]);
i--;
}
_mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
free(rgba);
return;
}
}
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
}
/*
printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
combine->ModeRGB,
combine->ModeA,
combine->SourceRGB[0],
combine->SourceA[0],
combine->SourceRGB[1],
combine->SourceA[1]);
*/
/*
* Do operand setup for up to 4 operands. Loop over the terms.
*/
for (term = 0; term < numArgsRGB; term++) {
const GLenum srcRGB = combine->SourceRGB[term];
const GLenum operandRGB = combine->OperandRGB[term];
switch (srcRGB) {
case GL_TEXTURE:
argRGB[term] = get_texel_array(swrast, unit);
break;
case GL_PRIMARY_COLOR:
argRGB[term] = primary_rgba;
break;
case GL_PREVIOUS:
argRGB[term] = rgba;
break;
case GL_CONSTANT:
{
float4_array c = ccolor[term];
GLfloat red = textureUnit->EnvColor[0];
GLfloat green = textureUnit->EnvColor[1];
GLfloat blue = textureUnit->EnvColor[2];
GLfloat alpha = textureUnit->EnvColor[3];
for (i = 0; i < n; i++) {
ASSIGN_4V(c[i], red, green, blue, alpha);
}
argRGB[term] = ccolor[term];
}
break;
/* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
*/
case GL_ZERO:
{
float4_array c = ccolor[term];
for (i = 0; i < n; i++) {
ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
}
argRGB[term] = ccolor[term];
}
break;
case GL_ONE:
{
float4_array c = ccolor[term];
for (i = 0; i < n; i++) {
ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
}
argRGB[term] = ccolor[term];
}
break;
default:
/* ARB_texture_env_crossbar source */
{
const GLuint srcUnit = srcRGB - GL_TEXTURE0;
assert(srcUnit < ctx->Const.MaxTextureUnits);
if (!ctx->Texture.Unit[srcUnit]._Current)
goto end;
argRGB[term] = get_texel_array(swrast, srcUnit);
}
}
if (operandRGB != GL_SRC_COLOR) {
float4_array src = argRGB[term];
float4_array dst = ccolor[term];
/* point to new arg[term] storage */
argRGB[term] = ccolor[term];
switch (operandRGB) {
case GL_ONE_MINUS_SRC_COLOR:
for (i = 0; i < n; i++) {
dst[i][RCOMP] = 1.0F - src[i][RCOMP];
dst[i][GCOMP] = 1.0F - src[i][GCOMP];
dst[i][BCOMP] = 1.0F - src[i][BCOMP];
}
break;
case GL_SRC_ALPHA:
for (i = 0; i < n; i++) {
dst[i][RCOMP] =
dst[i][GCOMP] =
dst[i][BCOMP] = src[i][ACOMP];
}
break;
case GL_ONE_MINUS_SRC_ALPHA:
for (i = 0; i < n; i++) {
dst[i][RCOMP] =
dst[i][GCOMP] =
dst[i][BCOMP] = 1.0F - src[i][ACOMP];
}
break;
default:
_mesa_problem(ctx, "Bad operandRGB");
}
}
}
/*
* Set up the argA[term] pointers
*/
for (term = 0; term < numArgsA; term++) {
const GLenum srcA = combine->SourceA[term];
const GLenum operandA = combine->OperandA[term];
switch (srcA) {
case GL_TEXTURE:
argA[term] = get_texel_array(swrast, unit);
break;
case GL_PRIMARY_COLOR:
argA[term] = primary_rgba;
break;
case GL_PREVIOUS:
argA[term] = rgba;
break;
case GL_CONSTANT:
{
float4_array c = ccolor[term];
GLfloat alpha = textureUnit->EnvColor[3];
for (i = 0; i < n; i++)
c[i][ACOMP] = alpha;
argA[term] = ccolor[term];
}
break;
/* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
*/
case GL_ZERO:
{
float4_array c = ccolor[term];
for (i = 0; i < n; i++)
c[i][ACOMP] = 0.0F;
argA[term] = ccolor[term];
}
break;
case GL_ONE:
{
float4_array c = ccolor[term];
for (i = 0; i < n; i++)
c[i][ACOMP] = 1.0F;
argA[term] = ccolor[term];
}
break;
default:
/* ARB_texture_env_crossbar source */
{
const GLuint srcUnit = srcA - GL_TEXTURE0;
assert(srcUnit < ctx->Const.MaxTextureUnits);
if (!ctx->Texture.Unit[srcUnit]._Current)
goto end;
argA[term] = get_texel_array(swrast, srcUnit);
}
}
if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
float4_array src = argA[term];
float4_array dst = ccolor[term];
argA[term] = ccolor[term];
for (i = 0; i < n; i++) {
dst[i][ACOMP] = 1.0F - src[i][ACOMP];
}
}
}
/* RGB channel combine */
{
float4_array arg0 = argRGB[0];
float4_array arg1 = argRGB[1];
float4_array arg2 = argRGB[2];
float4_array arg3 = argRGB[3];
switch (combine->ModeRGB) {
case GL_REPLACE:
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
}
break;
case GL_MODULATE:
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
}
break;
case GL_ADD:
if (textureUnit->EnvMode == GL_COMBINE4_NV) {
/* (a * b) + (c * d) */
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
}
}
else {
/* 2-term addition */
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
}
}
break;
case GL_ADD_SIGNED:
if (textureUnit->EnvMode == GL_COMBINE4_NV) {
/* (a * b) + (c * d) - 0.5 */
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5F) * scaleRGB;
rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5F) * scaleRGB;
rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5F) * scaleRGB;
}
}
else {
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5F) * scaleRGB;
rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5F) * scaleRGB;
rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5F) * scaleRGB;
}
}
break;
case GL_INTERPOLATE:
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
}
break;
case GL_SUBTRACT:
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
}
break;
case GL_DOT3_RGB_EXT:
case GL_DOT3_RGBA_EXT:
/* Do not scale the result by 1 2 or 4 */
for (i = 0; i < n; i++) {
GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
(arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
(arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
* 4.0F;
dot = CLAMP(dot, 0.0F, 1.0F);
rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
}
break;
case GL_DOT3_RGB:
case GL_DOT3_RGBA:
/* DO scale the result by 1 2 or 4 */
for (i = 0; i < n; i++) {
GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
(arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
(arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
* 4.0F * scaleRGB;
dot = CLAMP(dot, 0.0F, 1.0F);
rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
}
break;
case GL_MODULATE_ADD_ATI:
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
arg1[i][RCOMP]) * scaleRGB;
rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
arg1[i][GCOMP]) * scaleRGB;
rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
arg1[i][BCOMP]) * scaleRGB;
}
break;
case GL_MODULATE_SIGNED_ADD_ATI:
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
arg1[i][RCOMP] - 0.5F) * scaleRGB;
rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
arg1[i][GCOMP] - 0.5F) * scaleRGB;
rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
arg1[i][BCOMP] - 0.5F) * scaleRGB;
}
break;
case GL_MODULATE_SUBTRACT_ATI:
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
arg1[i][RCOMP]) * scaleRGB;
rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
arg1[i][GCOMP]) * scaleRGB;
rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
arg1[i][BCOMP]) * scaleRGB;
}
break;
default:
_mesa_problem(ctx, "invalid combine mode");
}
}
/* Alpha channel combine */
{
float4_array arg0 = argA[0];
float4_array arg1 = argA[1];
float4_array arg2 = argA[2];
float4_array arg3 = argA[3];
switch (combine->ModeA) {
case GL_REPLACE:
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
}
break;
case GL_MODULATE:
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
}
break;
case GL_ADD:
if (textureUnit->EnvMode == GL_COMBINE4_NV) {
/* (a * b) + (c * d) */
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
}
}
else {
/* two-term add */
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
}
}
break;
case GL_ADD_SIGNED:
if (textureUnit->EnvMode == GL_COMBINE4_NV) {
/* (a * b) + (c * d) - 0.5 */
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
arg2[i][ACOMP] * arg3[i][ACOMP] -
0.5F) * scaleA;
}
}
else {
/* a + b - 0.5 */
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
}
}
break;
case GL_INTERPOLATE:
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
* scaleA;
}
break;
case GL_SUBTRACT:
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
}
break;
case GL_MODULATE_ADD_ATI:
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
+ arg1[i][ACOMP]) * scaleA;
}
break;
case GL_MODULATE_SIGNED_ADD_ATI:
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
arg1[i][ACOMP] - 0.5F) * scaleA;
}
break;
case GL_MODULATE_SUBTRACT_ATI:
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
- arg1[i][ACOMP]) * scaleA;
}
break;
default:
_mesa_problem(ctx, "invalid combine mode");
}
}
/* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
* This is kind of a kludge. It would have been better if the spec
* were written such that the GL_COMBINE_ALPHA value could be set to
* GL_DOT3.
*/
if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
combine->ModeRGB == GL_DOT3_RGBA) {
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = rgba[i][RCOMP];
}
}
for (i = 0; i < n; i++) {
UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
}
/* The span->array->rgba values are of CHAN type so set
* span->array->ChanType field accordingly.
*/
span->array->ChanType = CHAN_TYPE;
end:
for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
free(ccolor[i]);
}
free(rgba);
}
/**
* Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
* See GL_EXT_texture_swizzle.
*/
static void
swizzle_texels(GLuint swizzle, GLuint count, float4_array texels)
{
const GLuint swzR = GET_SWZ(swizzle, 0);
const GLuint swzG = GET_SWZ(swizzle, 1);
const GLuint swzB = GET_SWZ(swizzle, 2);
const GLuint swzA = GET_SWZ(swizzle, 3);
GLfloat vector[6];
GLuint i;
vector[SWIZZLE_ZERO] = 0;
vector[SWIZZLE_ONE] = 1.0F;
for (i = 0; i < count; i++) {
vector[SWIZZLE_X] = texels[i][0];
vector[SWIZZLE_Y] = texels[i][1];
vector[SWIZZLE_Z] = texels[i][2];
vector[SWIZZLE_W] = texels[i][3];
texels[i][RCOMP] = vector[swzR];
texels[i][GCOMP] = vector[swzG];
texels[i][BCOMP] = vector[swzB];
texels[i][ACOMP] = vector[swzA];
}
}
/**
* Apply texture mapping to a span of fragments.
*/
void
_swrast_texture_span( struct gl_context *ctx, SWspan *span )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
float4_array primary_rgba;
GLuint unit;
if (!swrast->TexelBuffer) {
#ifdef _OPENMP
const GLint maxThreads = omp_get_max_threads();
/* TexelBuffer memory allocation needs to be done in a critical section
* as this code runs in a parallel loop.
* When entering the section, first check if TexelBuffer has been
* initialized already by another thread while this thread was waiting.
*/
#pragma omp critical
if (!swrast->TexelBuffer) {
#else
const GLint maxThreads = 1;
#endif
/* TexelBuffer is also global and normally shared by all SWspan
* instances; when running with multiple threads, create one per
* thread.
*/
swrast->TexelBuffer =
malloc(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits * maxThreads *
SWRAST_MAX_WIDTH * 4 * sizeof(GLfloat));
#ifdef _OPENMP
} /* critical section */
#endif
if (!swrast->TexelBuffer) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
return;
}
}
primary_rgba = malloc(span->end * 4 * sizeof(GLfloat));
if (!primary_rgba) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span");
return;
}
assert(span->end <= SWRAST_MAX_WIDTH);
/*
* Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
*/
if (swrast->_TextureCombinePrimary) {
GLuint i;
for (i = 0; i < span->end; i++) {
primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
}
}
/*
* Must do all texture sampling before combining in order to
* accommodate GL_ARB_texture_env_crossbar.
*/
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
if (texUnit->_Current) {
const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
span->array->attribs[VARYING_SLOT_TEX0 + unit];
const struct gl_texture_object *curObj = texUnit->_Current;
const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
GLfloat *lambda = span->array->lambda[unit];
float4_array texels = get_texel_array(swrast, unit);
/* adjust texture lod (lambda) */
if (span->arrayMask & SPAN_LAMBDA) {
if (texUnit->LodBias + samp->Attrib.LodBias != 0.0F) {
/* apply LOD bias, but don't clamp yet */
const GLfloat bias = CLAMP(texUnit->LodBias + samp->Attrib.LodBias,
-ctx->Const.MaxTextureLodBias,
ctx->Const.MaxTextureLodBias);
GLuint i;
for (i = 0; i < span->end; i++) {
lambda[i] += bias;
}
}
if (samp->Attrib.MinLod != -1000.0F ||
samp->Attrib.MaxLod != 1000.0F) {
/* apply LOD clamping to lambda */
const GLfloat min = samp->Attrib.MinLod;
const GLfloat max = samp->Attrib.MaxLod;
GLuint i;
for (i = 0; i < span->end; i++) {
GLfloat l = lambda[i];
lambda[i] = CLAMP(l, min, max);
}
}
}
else if (samp->Attrib.MaxAnisotropy > 1.0F &&
samp->Attrib.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
/* sample_lambda_2d_aniso is beeing used as texture_sample_func,
* it requires the current SWspan *span as an additional parameter.
* In order to keep the same function signature, the unused lambda
* parameter will be modified to actually contain the SWspan pointer.
* This is a Hack. To make it right, the texture_sample_func
* signature and all implementing functions need to be modified.
*/
/* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
lambda = (GLfloat *)span;
}
/* Sample the texture (span->end = number of fragments) */
swrast->TextureSample[unit]( ctx, samp,
ctx->Texture.Unit[unit]._Current,
span->end, texcoords, lambda, texels );
/* GL_EXT_texture_swizzle */
if (curObj->Attrib._Swizzle != SWIZZLE_NOOP) {
swizzle_texels(curObj->Attrib._Swizzle, span->end, texels);
}
}
}
/*
* OK, now apply the texture (aka texture combine/blend).
* We modify the span->color.rgba values.
*/
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
if (ctx->Texture.Unit[unit]._Current)
texture_combine(ctx, unit, primary_rgba, swrast->TexelBuffer, span);
}
free(primary_rgba);
}

View File

@ -1,37 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_TEXCOMBINE_H
#define S_TEXCOMBINE_H
#include "s_span.h"
struct gl_context;
extern void
_swrast_texture_span( struct gl_context *ctx, SWspan *span );
#endif

View File

@ -1,368 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* Copyright (c) 2009 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file s_texfetch.c
*
* Texel fetch/store functions
*
* \author Gareth Hughes
*/
#include "main/errors.h"
#include "main/macros.h"
#include "main/texcompress.h"
#include "main/texcompress_fxt1.h"
#include "main/texcompress_s3tc.h"
#include "main/texcompress_rgtc.h"
#include "main/texcompress_etc.h"
#include "main/teximage.h"
#include "main/samplerobj.h"
#include "s_context.h"
#include "s_texfetch.h"
#include "util/format_rgb9e5.h"
#include "util/format_r11g11b10f.h"
#include "util/format_srgb.h"
/* Texel fetch routines for all supported formats
*/
#define DIM 1
#include "s_texfetch_tmp.h"
#define DIM 2
#include "s_texfetch_tmp.h"
#define DIM 3
#include "s_texfetch_tmp.h"
/**
* All compressed texture texel fetching is done though this function.
* Basically just call a core-Mesa texel fetch function.
*/
static void
fetch_compressed(const struct swrast_texture_image *swImage,
GLint i, GLint j, GLint k, GLfloat *texel)
{
/* The FetchCompressedTexel function takes an integer pixel rowstride,
* while the image's rowstride is bytes per row of blocks.
*/
GLuint bw, bh;
GLuint texelBytes = _mesa_get_format_bytes(swImage->Base.TexFormat);
_mesa_get_format_block_size(swImage->Base.TexFormat, &bw, &bh);
assert(swImage->RowStride * bw % texelBytes == 0);
swImage->FetchCompressedTexel(swImage->ImageSlices[k],
swImage->RowStride * bw / texelBytes,
i, j, texel);
}
/**
* Null texel fetch function.
*
* Have to have this so the FetchTexel function pointer is never NULL.
*/
static void fetch_null_texelf( const struct swrast_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel )
{
(void) texImage; (void) i; (void) j; (void) k;
texel[RCOMP] = 0.0;
texel[GCOMP] = 0.0;
texel[BCOMP] = 0.0;
texel[ACOMP] = 0.0;
_mesa_warning(NULL, "fetch_null_texelf() called!");
}
#define FETCH_FUNCS(NAME) \
[MESA_FORMAT_ ## NAME] = { \
fetch_texel_1d_ ## NAME, \
fetch_texel_2d_ ## NAME, \
fetch_texel_3d_ ## NAME, \
}
#define FETCH_COMPRESSED(NAME) \
[MESA_FORMAT_ ## NAME] = { \
fetch_compressed, \
fetch_compressed, \
fetch_compressed \
}
/**
* Table to map MESA_FORMAT_ to texel fetch/store funcs.
*/
static struct {
FetchTexelFunc Fetch1D;
FetchTexelFunc Fetch2D;
FetchTexelFunc Fetch3D;
}
texfetch_funcs[] =
{
/* Packed unorm formats */
FETCH_FUNCS(A8B8G8R8_UNORM),
FETCH_FUNCS(X8B8G8R8_UNORM),
FETCH_FUNCS(R8G8B8A8_UNORM),
FETCH_FUNCS(R8G8B8X8_UNORM),
FETCH_FUNCS(B8G8R8A8_UNORM),
FETCH_FUNCS(B8G8R8X8_UNORM),
FETCH_FUNCS(A8R8G8B8_UNORM),
FETCH_FUNCS(X8R8G8B8_UNORM),
FETCH_FUNCS(B5G6R5_UNORM),
FETCH_FUNCS(R5G6B5_UNORM),
FETCH_FUNCS(B4G4R4A4_UNORM),
FETCH_FUNCS(A4R4G4B4_UNORM),
FETCH_FUNCS(A1B5G5R5_UNORM),
FETCH_FUNCS(B5G5R5A1_UNORM),
FETCH_FUNCS(A1R5G5B5_UNORM),
FETCH_FUNCS(L4A4_UNORM),
FETCH_FUNCS(B2G3R3_UNORM),
FETCH_FUNCS(B10G10R10A2_UNORM),
FETCH_FUNCS(R10G10B10A2_UNORM),
FETCH_FUNCS(S8_UINT_Z24_UNORM),
[MESA_FORMAT_X8_UINT_Z24_UNORM] = {
fetch_texel_1d_S8_UINT_Z24_UNORM,
fetch_texel_2d_S8_UINT_Z24_UNORM,
fetch_texel_3d_S8_UINT_Z24_UNORM
},
FETCH_FUNCS(Z24_UNORM_S8_UINT),
[MESA_FORMAT_Z24_UNORM_X8_UINT] = {
fetch_texel_1d_Z24_UNORM_S8_UINT,
fetch_texel_2d_Z24_UNORM_S8_UINT,
fetch_texel_3d_Z24_UNORM_S8_UINT
},
FETCH_FUNCS(YCBCR),
FETCH_FUNCS(YCBCR_REV),
/* Array unorm formats */
FETCH_FUNCS(A_UNORM8),
FETCH_FUNCS(A_UNORM16),
FETCH_FUNCS(L_UNORM8),
FETCH_FUNCS(L_UNORM16),
FETCH_FUNCS(LA_UNORM8),
FETCH_FUNCS(LA_UNORM16),
FETCH_FUNCS(I_UNORM8),
FETCH_FUNCS(I_UNORM16),
FETCH_FUNCS(R_UNORM8),
FETCH_FUNCS(R_UNORM16),
FETCH_FUNCS(RG_UNORM8),
FETCH_FUNCS(RG_UNORM16),
FETCH_FUNCS(BGR_UNORM8),
FETCH_FUNCS(RGB_UNORM8),
FETCH_FUNCS(RGBA_UNORM16),
FETCH_FUNCS(RGBX_UNORM16),
FETCH_FUNCS(Z_UNORM16),
FETCH_FUNCS(Z_UNORM32),
/* Packed signed/normalized formats */
FETCH_FUNCS(A8B8G8R8_SNORM),
FETCH_FUNCS(X8B8G8R8_SNORM),
FETCH_FUNCS(R8G8B8A8_SNORM),
/* Array signed/normalized formats */
FETCH_FUNCS(A_SNORM8),
FETCH_FUNCS(A_SNORM16),
FETCH_FUNCS(L_SNORM8),
FETCH_FUNCS(L_SNORM16),
FETCH_FUNCS(LA_SNORM8),
FETCH_FUNCS(LA_SNORM16),
FETCH_FUNCS(I_SNORM8),
FETCH_FUNCS(I_SNORM16),
FETCH_FUNCS(R_SNORM8),
FETCH_FUNCS(R_SNORM16),
FETCH_FUNCS(RG_SNORM8),
FETCH_FUNCS(RG_SNORM16),
FETCH_FUNCS(RGB_SNORM16),
FETCH_FUNCS(RGBA_SNORM16),
/* Packed sRGB formats */
FETCH_FUNCS(A8B8G8R8_SRGB),
FETCH_FUNCS(B8G8R8A8_SRGB),
FETCH_FUNCS(A8R8G8B8_SRGB),
FETCH_FUNCS(R8G8B8A8_SRGB),
FETCH_FUNCS(R8G8B8X8_SRGB),
FETCH_FUNCS(X8B8G8R8_SRGB),
/* Array sRGB formats */
FETCH_FUNCS(R_SRGB8),
FETCH_FUNCS(L_SRGB8),
FETCH_FUNCS(LA_SRGB8),
FETCH_FUNCS(BGR_SRGB8),
/* Packed float formats */
FETCH_FUNCS(R9G9B9E5_FLOAT),
FETCH_FUNCS(R11G11B10_FLOAT),
FETCH_FUNCS(Z32_FLOAT_S8X24_UINT),
/* Array float formats */
FETCH_FUNCS(A_FLOAT16),
FETCH_FUNCS(A_FLOAT32),
FETCH_FUNCS(L_FLOAT16),
FETCH_FUNCS(L_FLOAT32),
FETCH_FUNCS(LA_FLOAT16),
FETCH_FUNCS(LA_FLOAT32),
FETCH_FUNCS(I_FLOAT16),
FETCH_FUNCS(I_FLOAT32),
FETCH_FUNCS(R_FLOAT16),
FETCH_FUNCS(R_FLOAT32),
FETCH_FUNCS(RG_FLOAT16),
FETCH_FUNCS(RG_FLOAT32),
FETCH_FUNCS(RGB_FLOAT16),
FETCH_FUNCS(RGB_FLOAT32),
FETCH_FUNCS(RGBA_FLOAT16),
FETCH_FUNCS(RGBA_FLOAT32),
FETCH_FUNCS(RGBX_FLOAT16),
FETCH_FUNCS(RGBX_FLOAT32),
[MESA_FORMAT_Z_FLOAT32] = {
fetch_texel_1d_R_FLOAT32, /* Reuse the R32F functions. */
fetch_texel_2d_R_FLOAT32,
fetch_texel_3d_R_FLOAT32
},
/* Packed signed/unsigned non-normalized integer formats */
/* Array signed/unsigned non-normalized integer formats */
FETCH_FUNCS(RGBA_UINT16),
FETCH_FUNCS(RGBA_UINT32),
FETCH_FUNCS(RGBA_SINT8),
FETCH_FUNCS(RGBA_SINT16),
FETCH_FUNCS(RGBA_SINT32),
/* DXT compressed formats */
FETCH_COMPRESSED(RGB_DXT1),
FETCH_COMPRESSED(RGBA_DXT1),
FETCH_COMPRESSED(RGBA_DXT3),
FETCH_COMPRESSED(RGBA_DXT5),
/* DXT sRGB compressed formats */
FETCH_COMPRESSED(SRGB_DXT1),
FETCH_COMPRESSED(SRGBA_DXT1),
FETCH_COMPRESSED(SRGBA_DXT3),
FETCH_COMPRESSED(SRGBA_DXT5),
/* FXT1 compressed formats */
FETCH_COMPRESSED(RGB_FXT1),
FETCH_COMPRESSED(RGBA_FXT1),
/* RGTC compressed formats */
FETCH_COMPRESSED(R_RGTC1_UNORM),
FETCH_COMPRESSED(R_RGTC1_SNORM),
FETCH_COMPRESSED(RG_RGTC2_UNORM),
FETCH_COMPRESSED(RG_RGTC2_SNORM),
/* LATC1/2 compressed formats */
FETCH_COMPRESSED(L_LATC1_UNORM),
FETCH_COMPRESSED(L_LATC1_SNORM),
FETCH_COMPRESSED(LA_LATC2_UNORM),
FETCH_COMPRESSED(LA_LATC2_SNORM),
/* ETC1/2 compressed formats */
FETCH_COMPRESSED(ETC1_RGB8),
FETCH_COMPRESSED(ETC2_RGB8),
FETCH_COMPRESSED(ETC2_SRGB8),
FETCH_COMPRESSED(ETC2_RGBA8_EAC),
FETCH_COMPRESSED(ETC2_SRGB8_ALPHA8_EAC),
FETCH_COMPRESSED(ETC2_R11_EAC),
FETCH_COMPRESSED(ETC2_RG11_EAC),
FETCH_COMPRESSED(ETC2_SIGNED_R11_EAC),
FETCH_COMPRESSED(ETC2_SIGNED_RG11_EAC),
FETCH_COMPRESSED(ETC2_RGB8_PUNCHTHROUGH_ALPHA1),
FETCH_COMPRESSED(ETC2_SRGB8_PUNCHTHROUGH_ALPHA1),
FETCH_COMPRESSED(BPTC_RGBA_UNORM),
FETCH_COMPRESSED(BPTC_SRGB_ALPHA_UNORM),
FETCH_COMPRESSED(BPTC_RGB_SIGNED_FLOAT),
FETCH_COMPRESSED(BPTC_RGB_UNSIGNED_FLOAT),
};
/**
* Initialize the texture image's FetchTexel methods.
*/
static void
set_fetch_functions(const struct gl_sampler_object *samp,
struct swrast_texture_image *texImage, GLuint dims)
{
mesa_format format = texImage->Base.TexFormat;
if (samp->Attrib.sRGBDecode == GL_SKIP_DECODE_EXT)
format = _mesa_get_srgb_format_linear(format);
texImage->FetchTexel = NULL;
if (format < ARRAY_SIZE(texfetch_funcs)) {
switch (dims) {
case 1:
texImage->FetchTexel = texfetch_funcs[format].Fetch1D;
break;
case 2:
texImage->FetchTexel = texfetch_funcs[format].Fetch2D;
break;
case 3:
texImage->FetchTexel = texfetch_funcs[format].Fetch3D;
break;
default:
assert(!"Bad dims in set_fetch_functions()");
}
}
if (!texImage->FetchTexel)
texImage->FetchTexel = fetch_null_texelf;
texImage->FetchCompressedTexel = _mesa_get_compressed_fetch_func(format);
assert(texImage->FetchTexel);
}
void
_mesa_update_fetch_functions(struct gl_context *ctx, GLuint unit)
{
struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
struct gl_sampler_object *samp;
GLuint face, i;
GLuint dims;
if (!texObj)
return;
samp = _mesa_get_samplerobj(ctx, unit);
dims = _mesa_get_texture_dimensions(texObj->Target);
for (face = 0; face < 6; face++) {
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
if (texObj->Image[face][i]) {
set_fetch_functions(samp,
swrast_texture_image(texObj->Image[face][i]),
dims);
}
}
}
}

View File

@ -1,35 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* Copyright (c) 2009 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_TEXFETCH_H
#define S_TEXFETCH_H
#include "swrast/s_context.h"
void
_mesa_update_fetch_functions(struct gl_context *ctx, GLuint unit);
#endif /* S_TEXFETCH_H */

View File

@ -1,190 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* Copyright (c) 2008-2009 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file texfetch_tmp.h
* Texel fetch functions template.
*
* This template file is used by texfetch.c to generate texel fetch functions
* for 1-D, 2-D and 3-D texture images.
*
* It should be expanded by defining \p DIM as the number texture dimensions
* (1, 2 or 3). According to the value of \p DIM a series of macros is defined
* for the texel lookup in the gl_texture_image::Data.
*
* \author Gareth Hughes
* \author Brian Paul
*/
#include <format_unpack.h>
#if DIM == 1
#define TEXEL_ADDR( type, image, i, j, k, size ) \
((void) (j), (void) (k), ((type *)(image)->ImageSlices[0] + (i) * (size)))
#define FETCH(x) fetch_texel_1d_##x
#elif DIM == 2
#define TEXEL_ADDR( type, image, i, j, k, size ) \
((void) (k), \
((type *)((GLubyte *) (image)->ImageSlices[0] + (image)->RowStride * (j)) + \
(i) * (size)))
#define FETCH(x) fetch_texel_2d_##x
#elif DIM == 3
#define TEXEL_ADDR( type, image, i, j, k, size ) \
((type *)((GLubyte *) (image)->ImageSlices[k] + \
(image)->RowStride * (j)) + (i) * (size))
#define FETCH(x) fetch_texel_3d_##x
#else
#error illegal number of texture dimensions
#endif
#define FETCH_Z(x, type, size) \
static void \
FETCH(x) (const struct swrast_texture_image *texImage, \
GLint i, GLint j, GLint k, GLfloat *texel) \
{ \
const type *src = TEXEL_ADDR(type, texImage, i, j, k, size); \
_mesa_unpack_float_z_row(MESA_FORMAT_##x, 1, src, texel); \
}
#define FETCH_RGBA(x, type, size) \
static void \
FETCH(x) (const struct swrast_texture_image *texImage, \
GLint i, GLint j, GLint k, GLfloat *texel) \
{ \
const type *src = TEXEL_ADDR(type, texImage, i, j, k, size); \
_mesa_unpack_rgba_row(MESA_FORMAT_##x, 1, src, (GLvoid *)texel); \
}
FETCH_Z(Z_UNORM32, GLuint, 1)
FETCH_Z(Z_UNORM16, GLushort, 1)
FETCH_Z(S8_UINT_Z24_UNORM, GLuint, 1) /* only return Z, not stencil data */
FETCH_Z(Z24_UNORM_S8_UINT, GLuint, 1) /* only return Z, not stencil data */
FETCH_Z(Z32_FLOAT_S8X24_UINT, GLfloat, 2)
FETCH_RGBA(RGBA_FLOAT32, GLfloat, 4)
FETCH_RGBA(RGBA_FLOAT16, GLhalfARB, 4)
FETCH_RGBA(RGB_FLOAT32, GLfloat, 3)
FETCH_RGBA(RGB_FLOAT16, GLhalfARB, 3)
FETCH_RGBA(A_FLOAT32, GLfloat, 1)
FETCH_RGBA(A_FLOAT16, GLhalfARB, 1)
FETCH_RGBA(L_FLOAT32, GLfloat, 1)
FETCH_RGBA(L_FLOAT16, GLhalfARB, 1)
FETCH_RGBA(LA_FLOAT32, GLfloat, 2)
FETCH_RGBA(LA_FLOAT16, GLhalfARB, 2)
FETCH_RGBA(I_FLOAT32, GLfloat, 1)
FETCH_RGBA(I_FLOAT16, GLhalfARB, 1)
FETCH_RGBA(R_FLOAT32, GLfloat, 1)
FETCH_RGBA(R_FLOAT16, GLhalfARB, 1)
FETCH_RGBA(RG_FLOAT32, GLfloat, 2)
FETCH_RGBA(RG_FLOAT16, GLhalfARB, 2)
FETCH_RGBA(A8B8G8R8_UNORM, GLuint, 1)
FETCH_RGBA(R8G8B8A8_UNORM, GLuint, 1)
FETCH_RGBA(B8G8R8A8_UNORM, GLuint, 1)
FETCH_RGBA(A8R8G8B8_UNORM, GLuint, 1)
FETCH_RGBA(X8B8G8R8_UNORM, GLuint, 1)
FETCH_RGBA(R8G8B8X8_UNORM, GLuint, 1)
FETCH_RGBA(B8G8R8X8_UNORM, GLuint, 1)
FETCH_RGBA(X8R8G8B8_UNORM, GLuint, 1)
FETCH_RGBA(BGR_UNORM8, GLubyte, 3)
FETCH_RGBA(RGB_UNORM8, GLubyte, 3)
FETCH_RGBA(B5G6R5_UNORM, GLushort, 1)
FETCH_RGBA(R5G6B5_UNORM, GLushort, 1)
FETCH_RGBA(B4G4R4A4_UNORM, GLushort, 1)
FETCH_RGBA(A4R4G4B4_UNORM, GLushort, 1)
FETCH_RGBA(A1B5G5R5_UNORM, GLushort, 1)
FETCH_RGBA(B5G5R5A1_UNORM, GLushort, 1)
FETCH_RGBA(A1R5G5B5_UNORM, GLushort, 1)
FETCH_RGBA(B10G10R10A2_UNORM, GLuint, 1)
FETCH_RGBA(R10G10B10A2_UNORM, GLuint, 1)
FETCH_RGBA(RG_UNORM8, GLubyte, 2)
FETCH_RGBA(L4A4_UNORM, GLubyte, 1)
FETCH_RGBA(R_UNORM8, GLubyte, 1)
FETCH_RGBA(R_UNORM16, GLushort, 1)
FETCH_RGBA(LA_UNORM8, GLubyte, 2)
FETCH_RGBA(RG_UNORM16, GLushort, 2)
FETCH_RGBA(B2G3R3_UNORM, GLubyte, 1)
FETCH_RGBA(A_UNORM8, GLubyte, 1)
FETCH_RGBA(A_UNORM16, GLushort, 1)
FETCH_RGBA(L_UNORM8, GLubyte, 1)
FETCH_RGBA(L_UNORM16, GLushort, 1)
FETCH_RGBA(LA_UNORM16, GLushort, 2)
FETCH_RGBA(I_UNORM8, GLubyte, 1)
FETCH_RGBA(I_UNORM16, GLushort, 1)
FETCH_RGBA(BGR_SRGB8, GLubyte, 3)
FETCH_RGBA(A8B8G8R8_SRGB, GLuint, 1)
FETCH_RGBA(B8G8R8A8_SRGB, GLuint, 1)
FETCH_RGBA(A8R8G8B8_SRGB, GLuint, 1)
FETCH_RGBA(R8G8B8A8_SRGB, GLuint, 1)
FETCH_RGBA(R8G8B8X8_SRGB, GLuint, 1)
FETCH_RGBA(X8B8G8R8_SRGB, GLuint, 1)
FETCH_RGBA(R_SRGB8, GLubyte, 1)
FETCH_RGBA(L_SRGB8, GLubyte, 1)
FETCH_RGBA(LA_SRGB8, GLubyte, 2)
FETCH_RGBA(RGBA_SINT8, GLbyte, 4)
FETCH_RGBA(RGBA_SINT16, GLshort, 4)
FETCH_RGBA(RGBA_SINT32, GLint, 4)
FETCH_RGBA(RGBA_UINT16, GLushort, 4)
FETCH_RGBA(RGBA_UINT32, GLuint, 4)
FETCH_RGBA(R_SNORM8, GLbyte, 1)
FETCH_RGBA(A_SNORM8, GLbyte, 1)
FETCH_RGBA(L_SNORM8, GLbyte, 1)
FETCH_RGBA(I_SNORM8, GLbyte, 1)
FETCH_RGBA(LA_SNORM8, GLbyte, 2)
FETCH_RGBA(RG_SNORM8, GLbyte, 2)
FETCH_RGBA(X8B8G8R8_SNORM, GLint, 1)
FETCH_RGBA(A8B8G8R8_SNORM, GLint, 1)
FETCH_RGBA(R8G8B8A8_SNORM, GLint, 1)
FETCH_RGBA(R_SNORM16, GLshort, 1)
FETCH_RGBA(A_SNORM16, GLshort, 1)
FETCH_RGBA(L_SNORM16, GLshort, 1)
FETCH_RGBA(I_SNORM16, GLshort, 1)
FETCH_RGBA(RG_SNORM16, GLshort, 2)
FETCH_RGBA(LA_SNORM16, GLshort, 2)
FETCH_RGBA(RGB_SNORM16, GLshort, 3)
FETCH_RGBA(RGBA_SNORM16, GLshort, 4)
FETCH_RGBA(RGBA_UNORM16, GLushort, 4)
FETCH_RGBA(RGBX_UNORM16, GLushort, 4)
FETCH_RGBA(RGBX_FLOAT16, GLhalfARB, 4)
FETCH_RGBA(RGBX_FLOAT32, GLfloat, 4)
FETCH_RGBA(YCBCR, GLushort, 1) /* Fetch texel from 1D, 2D or 3D ycbcr texture, returning RGBA. */
FETCH_RGBA(YCBCR_REV, GLushort, 1) /* Fetch texel from 1D, 2D or 3D ycbcr texture, returning RGBA. */
FETCH_RGBA(R9G9B9E5_FLOAT, GLuint, 1)
FETCH_RGBA(R11G11B10_FLOAT, GLuint, 1)
#undef TEXEL_ADDR
#undef DIM
#undef FETCH
#undef FETCH_Z
#undef FETCH_RGBA

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_TEXFILTER_H
#define S_TEXFILTER_H
#include "s_context.h"
struct gl_context;
struct gl_texture_object;
extern texture_sample_func
_swrast_choose_texture_sample_func( struct gl_context *ctx,
const struct gl_texture_object *tObj,
const struct gl_sampler_object *sampler);
#endif

View File

@ -1,102 +0,0 @@
#include "main/context.h"
#include "main/fbobject.h"
#include "main/macros.h"
#include "main/teximage.h"
#include "main/renderbuffer.h"
#include "swrast/swrast.h"
#include "swrast/s_context.h"
#include "swrast/s_texfetch.h"
/*
* Render-to-texture code for GL_EXT_framebuffer_object
*/
static void
delete_texture_wrapper(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
assert(rb->RefCount == 0);
free(rb);
}
/**
* Update the renderbuffer wrapper for rendering to a texture.
* For example, update the width, height of the RB based on the texture size,
* update the internal format info, etc.
*/
static void
update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
{
struct gl_renderbuffer *rb = att->Renderbuffer;
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
struct swrast_texture_image *swImage;
mesa_format format;
GLuint zOffset;
(void) ctx;
swImage = swrast_texture_image(rb->TexImage);
assert(swImage);
format = swImage->Base.TexFormat;
if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
zOffset = 0;
}
else {
zOffset = att->Zoffset;
}
/* Want to store linear values, not sRGB */
rb->Format = _mesa_get_srgb_format_linear(format);
srb->Buffer = swImage->ImageSlices[zOffset];
}
/**
* Called when rendering to a texture image begins, or when changing
* the dest mipmap level, cube face, etc.
* This is a fallback routine for software render-to-texture.
*
* Called via the glRenderbufferTexture1D/2D/3D() functions
* and elsewhere (such as glTexImage2D).
*
* The image we're rendering into is
* att->Texture->Image[att->CubeMapFace][att->TextureLevel];
* It'll never be NULL.
*
* \param fb the framebuffer object the texture is being bound to
* \param att the fb attachment point of the texture
*
* \sa _mesa_FramebufferRenderbuffer_sw
*/
void
_swrast_render_texture(struct gl_context *ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att)
{
struct gl_renderbuffer *rb = att->Renderbuffer;
(void) fb;
/* plug in our texture_renderbuffer-specific functions */
rb->Delete = delete_texture_wrapper;
update_wrapper(ctx, att);
}
void
_swrast_finish_render_texture(struct gl_context *ctx,
struct gl_renderbuffer *rb)
{
/* do nothing */
/* The renderbuffer texture wrapper will get deleted by the
* normal mechanism for deleting renderbuffers.
*/
(void) ctx;
(void) rb;
}

View File

@ -1,388 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Functions for mapping/unmapping texture images.
*/
#include "main/context.h"
#include "main/fbobject.h"
#include "main/teximage.h"
#include "main/texobj.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "swrast/swrast.h"
#include "swrast/s_context.h"
/**
* Allocate a new swrast_texture_image (a subclass of gl_texture_image).
* Called via ctx->Driver.NewTextureImage().
*/
struct gl_texture_image *
_swrast_new_texture_image( struct gl_context *ctx )
{
(void) ctx;
return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image);
}
/**
* Free a swrast_texture_image (a subclass of gl_texture_image).
* Called via ctx->Driver.DeleteTextureImage().
*/
void
_swrast_delete_texture_image(struct gl_context *ctx,
struct gl_texture_image *texImage)
{
/* Nothing special for the subclass yet */
_mesa_delete_texture_image(ctx, texImage);
}
static unsigned int
texture_slices(const struct gl_texture_image *texImage)
{
if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
return texImage->Height;
else
return texImage->Depth;
}
unsigned int
_swrast_teximage_slice_height(struct gl_texture_image *texImage)
{
/* For 1D array textures, the slices are all 1 pixel high, and Height is
* the number of slices.
*/
if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
return 1;
else
return texImage->Height;
}
/**
* Called via ctx->Driver.AllocTextureImageBuffer()
*/
GLboolean
_swrast_alloc_texture_image_buffer(struct gl_context *ctx,
struct gl_texture_image *texImage)
{
struct swrast_texture_image *swImg = swrast_texture_image(texImage);
GLuint bytesPerSlice;
GLuint slices = texture_slices(texImage);
GLuint i;
if (!_swrast_init_texture_image(texImage))
return GL_FALSE;
bytesPerSlice = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
_swrast_teximage_slice_height(texImage), 1);
assert(!swImg->Buffer);
swImg->Buffer = align_malloc(bytesPerSlice * slices, 512);
if (!swImg->Buffer)
return GL_FALSE;
/* RowStride and ImageSlices[] describe how to address texels in 'Data' */
swImg->RowStride = _mesa_format_row_stride(texImage->TexFormat,
texImage->Width);
for (i = 0; i < slices; i++) {
swImg->ImageSlices[i] = swImg->Buffer + bytesPerSlice * i;
}
return GL_TRUE;
}
/**
* Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to
* initialize the fields of swrast_texture_image without allocating the image
* buffer or initializing RowStride or the contents of ImageSlices.
*
* Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
*/
GLboolean
_swrast_init_texture_image(struct gl_texture_image *texImage)
{
struct swrast_texture_image *swImg = swrast_texture_image(texImage);
if ((texImage->Width == 1 || util_is_power_of_two_or_zero(texImage->Width2)) &&
(texImage->Height == 1 || util_is_power_of_two_or_zero(texImage->Height2)) &&
(texImage->Depth == 1 || util_is_power_of_two_or_zero(texImage->Depth2)))
swImg->_IsPowerOfTwo = GL_TRUE;
else
swImg->_IsPowerOfTwo = GL_FALSE;
/* Compute Width/Height/DepthScale for mipmap lod computation */
if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) {
/* scale = 1.0 since texture coords directly map to texels */
swImg->WidthScale = 1.0;
swImg->HeightScale = 1.0;
swImg->DepthScale = 1.0;
}
else {
swImg->WidthScale = (GLfloat) texImage->Width;
swImg->HeightScale = (GLfloat) texImage->Height;
swImg->DepthScale = (GLfloat) texImage->Depth;
}
assert(!swImg->ImageSlices);
swImg->ImageSlices = calloc(texture_slices(texImage), sizeof(void *));
if (!swImg->ImageSlices)
return GL_FALSE;
return GL_TRUE;
}
/**
* Called via ctx->Driver.FreeTextureImageBuffer()
*/
void
_swrast_free_texture_image_buffer(struct gl_context *ctx,
struct gl_texture_image *texImage)
{
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
align_free(swImage->Buffer);
swImage->Buffer = NULL;
free(swImage->ImageSlices);
swImage->ImageSlices = NULL;
}
/**
* Error checking for debugging only.
*/
static void
check_map_teximage(const struct gl_texture_image *texImage,
GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
{
if (texImage->TexObject->Target == GL_TEXTURE_1D)
assert(y == 0 && h == 1);
assert(x < texImage->Width || texImage->Width == 0);
assert(y < texImage->Height || texImage->Height == 0);
assert(x + w <= texImage->Width);
assert(y + h <= texImage->Height);
assert(slice < texture_slices(texImage));
}
/**
* Map a 2D slice of a texture image into user space.
* (x,y,w,h) defines a region of interest (ROI). Reading/writing texels
* outside of the ROI is undefined.
*
* \param texImage the texture image
* \param slice the 3D image slice or array texture slice
* \param x, y, w, h region of interest
* \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
* \param mapOut returns start of mapping of region of interest
* \param rowStrideOut returns row stride (in bytes)
*/
void
_swrast_map_teximage(struct gl_context *ctx,
struct gl_texture_image *texImage,
GLuint slice,
GLuint x, GLuint y, GLuint w, GLuint h,
GLbitfield mode,
GLubyte **mapOut,
GLint *rowStrideOut)
{
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
GLubyte *map;
GLint stride, texelSize;
GLuint bw, bh;
check_map_teximage(texImage, slice, x, y, w, h);
if (!swImage->Buffer) {
/* Either glTexImage was called with a NULL <pixels> argument or
* we ran out of memory when allocating texture memory,
*/
*mapOut = NULL;
*rowStrideOut = 0;
return;
}
texelSize = _mesa_get_format_bytes(texImage->TexFormat);
stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
_mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
assert(x % bw == 0);
assert(y % bh == 0);
/* This function can only be used with a swrast-allocated buffer, in which
* case ImageSlices is populated with pointers into Buffer.
*/
assert(swImage->Buffer);
assert(swImage->Buffer == swImage->ImageSlices[0]);
map = swImage->ImageSlices[slice];
/* apply x/y offset to map address */
map += stride * (y / bh) + texelSize * (x / bw);
*mapOut = map;
*rowStrideOut = stride;
}
void
_swrast_unmap_teximage(struct gl_context *ctx,
struct gl_texture_image *texImage,
GLuint slice)
{
/* nop */
}
void
_swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
{
const GLuint faces = _mesa_num_tex_faces(texObj->Target);
GLuint face, level;
for (face = 0; face < faces; face++) {
for (level = texObj->Attrib.BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
struct gl_texture_image *texImage = texObj->Image[face][level];
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
unsigned int i, slices;
if (!texImage)
continue;
/* In the case of a swrast-allocated texture buffer, the ImageSlices
* and RowStride are always available.
*/
if (swImage->Buffer) {
assert(swImage->ImageSlices[0] == swImage->Buffer);
continue;
}
if (!swImage->ImageSlices) {
swImage->ImageSlices =
calloc(texture_slices(texImage), sizeof(void *));
if (!swImage->ImageSlices)
continue;
}
slices = texture_slices(texImage);
for (i = 0; i < slices; i++) {
GLubyte *map;
GLint rowStride;
if (swImage->ImageSlices[i])
continue;
ctx->Driver.MapTextureImage(ctx, texImage, i,
0, 0,
texImage->Width, texImage->Height,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
&map, &rowStride);
swImage->ImageSlices[i] = map;
/* A swrast-using driver has to return the same rowstride for
* every slice of the same texture, since we don't track them
* separately.
*/
if (i == 0)
swImage->RowStride = rowStride;
else
assert(swImage->RowStride == rowStride);
}
}
}
}
void
_swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
{
const GLuint faces = _mesa_num_tex_faces(texObj->Target);
GLuint face, level;
for (face = 0; face < faces; face++) {
for (level = texObj->Attrib.BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
struct gl_texture_image *texImage = texObj->Image[face][level];
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
unsigned int i, slices;
if (!texImage)
continue;
if (swImage->Buffer)
return;
if (!swImage->ImageSlices)
continue;
slices = texture_slices(texImage);
for (i = 0; i < slices; i++) {
if (swImage->ImageSlices[i]) {
ctx->Driver.UnmapTextureImage(ctx, texImage, i);
swImage->ImageSlices[i] = NULL;
}
}
}
}
}
/**
* Map all textures for reading prior to software rendering.
*/
void
_swrast_map_textures(struct gl_context *ctx)
{
int unit;
for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
if (texObj)
_swrast_map_texture(ctx, texObj);
}
}
/**
* Unmap all textures for reading prior to software rendering.
*/
void
_swrast_unmap_textures(struct gl_context *ctx)
{
int unit;
for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
if (texObj)
_swrast_unmap_texture(ctx, texObj);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,50 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_TRIANGLES_H
#define S_TRIANGLES_H
#include "swrast.h"
extern GLboolean
_swrast_culltriangle( struct gl_context *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2);
extern void
_swrast_choose_triangle( struct gl_context *ctx );
extern void
_swrast_add_spec_terms_triangle( struct gl_context *ctx,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2 );
#endif

View File

@ -1,935 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Triangle Rasterizer Template
*
* This file is #include'd to generate custom triangle rasterizers.
*
* The following macros may be defined to indicate what auxillary information
* must be interpolated across the triangle:
* INTERP_Z - if defined, interpolate integer Z values
* INTERP_RGB - if defined, interpolate integer RGB values
* INTERP_ALPHA - if defined, interpolate integer Alpha values
* INTERP_INT_TEX - if defined, interpolate integer ST texcoords
* (fast, simple 2-D texture mapping, without
* perspective correction)
* INTERP_ATTRIBS - if defined, interpolate arbitrary attribs (texcoords,
* varying vars, etc) This also causes W to be
* computed for perspective correction).
*
* When one can directly address pixels in the color buffer the following
* macros can be defined and used to compute pixel addresses during
* rasterization (see pRow):
* PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
* BYTES_PER_ROW - number of bytes per row in the color buffer
* PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
* Y==0 at bottom of screen and increases upward.
*
* Similarly, for direct depth buffer access, this type is used for depth
* buffer addressing (see zRow):
* DEPTH_TYPE - either GLushort or GLuint
*
* Optionally, one may provide one-time setup code per triangle:
* SETUP_CODE - code which is to be executed once per triangle
*
* The following macro MUST be defined:
* RENDER_SPAN(span) - code to write a span of pixels.
*
* This code was designed for the origin to be in the lower-left corner.
*
* Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen!
*
*
* Some notes on rasterization accuracy:
*
* This code uses fixed point arithmetic (the GLfixed type) to iterate
* over the triangle edges and interpolate ancillary data (such as Z,
* color, secondary color, etc). The number of fractional bits in
* GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the
* accuracy of rasterization.
*
* If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest
* 1/16 of a pixel. If we're walking up a long, nearly vertical edge
* (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in
* GLfixed to walk the edge without error. If the maximum viewport
* height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits.
*
* Historically, Mesa has used 11 fractional bits in GLfixed, snaps
* vertices to 1/16 pixel and allowed a maximum viewport height of 2K
* pixels. 11 fractional bits is actually insufficient for accurately
* rasterizing some triangles. More recently, the maximum viewport
* height was increased to 4K pixels. Thus, Mesa should be using 16
* fractional bits in GLfixed. Unfortunately, there may be some issues
* with setting FIXED_FRAC_BITS=16, such as multiplication overflow.
* This will have to be examined in some detail...
*
* For now, if you find rasterization errors, particularly with tall,
* sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing
* SUB_PIXEL_BITS.
*/
#include "util/u_math.h"
#ifndef MAX_GLUINT
#define MAX_GLUINT 0xffffffffu
#endif
/*
* Some code we unfortunately need to prevent negative interpolated colors.
*/
#ifndef CLAMP_INTERPOLANT
#define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN) \
do { \
GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP; \
if (endVal < 0) { \
span.CHANNEL -= endVal; \
} \
if (span.CHANNEL < 0) { \
span.CHANNEL = 0; \
} \
} while (0)
#endif
static void NAME(struct gl_context *ctx, const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2 )
{
typedef struct {
const SWvertex *v0, *v1; /* Y(v0) < Y(v1) */
GLfloat dx; /* X(v1) - X(v0) */
GLfloat dy; /* Y(v1) - Y(v0) */
GLfloat dxdy; /* dx/dy */
GLfixed fdxdy; /* dx/dy in fixed-point */
GLfloat adjy; /* adjust from v[0]->fy to fsy, scaled */
GLfixed fsx; /* first sample point x coord */
GLfixed fsy;
GLfixed fx0; /* fixed pt X of lower endpoint */
GLint lines; /* number of lines to be sampled on this edge */
} EdgeT;
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
#ifdef INTERP_Z
const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF;
#define FixedToDepth(F) ((F) >> fixedToDepthShift)
#endif
EdgeT eMaj, eTop, eBot;
GLfloat oneOverArea;
const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */
GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign;
const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
SWspan span;
(void) swrast;
INIT_SPAN(span, GL_POLYGON);
span.y = 0; /* silence warnings */
#ifdef INTERP_Z
(void) fixedToDepthShift;
#endif
/*
printf("%s()\n", __func__);
printf(" %g, %g, %g\n",
v0->attrib[VARYING_SLOT_POS][0],
v0->attrib[VARYING_SLOT_POS][1],
v0->attrib[VARYING_SLOT_POS][2]);
printf(" %g, %g, %g\n",
v1->attrib[VARYING_SLOT_POS][0],
v1->attrib[VARYING_SLOT_POS][1],
v1->attrib[VARYING_SLOT_POS][2]);
printf(" %g, %g, %g\n",
v2->attrib[VARYING_SLOT_POS][0],
v2->attrib[VARYING_SLOT_POS][1],
v2->attrib[VARYING_SLOT_POS][2]);
*/
/* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
* And find the order of the 3 vertices along the Y axis.
*/
{
const GLfixed fy0 = FloatToFixed(v0->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask;
const GLfixed fy1 = FloatToFixed(v1->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask;
const GLfixed fy2 = FloatToFixed(v2->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask;
if (fy0 <= fy1) {
if (fy1 <= fy2) {
/* y0 <= y1 <= y2 */
vMin = v0; vMid = v1; vMax = v2;
vMin_fy = fy0; vMid_fy = fy1; vMax_fy = fy2;
}
else if (fy2 <= fy0) {
/* y2 <= y0 <= y1 */
vMin = v2; vMid = v0; vMax = v1;
vMin_fy = fy2; vMid_fy = fy0; vMax_fy = fy1;
}
else {
/* y0 <= y2 <= y1 */
vMin = v0; vMid = v2; vMax = v1;
vMin_fy = fy0; vMid_fy = fy2; vMax_fy = fy1;
bf = -bf;
}
}
else {
if (fy0 <= fy2) {
/* y1 <= y0 <= y2 */
vMin = v1; vMid = v0; vMax = v2;
vMin_fy = fy1; vMid_fy = fy0; vMax_fy = fy2;
bf = -bf;
}
else if (fy2 <= fy1) {
/* y2 <= y1 <= y0 */
vMin = v2; vMid = v1; vMax = v0;
vMin_fy = fy2; vMid_fy = fy1; vMax_fy = fy0;
bf = -bf;
}
else {
/* y1 <= y2 <= y0 */
vMin = v1; vMid = v2; vMax = v0;
vMin_fy = fy1; vMid_fy = fy2; vMax_fy = fy0;
}
}
/* fixed point X coords */
vMin_fx = FloatToFixed(vMin->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask;
vMid_fx = FloatToFixed(vMid->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask;
vMax_fx = FloatToFixed(vMax->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask;
}
/* vertex/edge relationship */
eMaj.v0 = vMin; eMaj.v1 = vMax; /*TODO: .v1's not needed */
eTop.v0 = vMid; eTop.v1 = vMax;
eBot.v0 = vMin; eBot.v1 = vMid;
/* compute deltas for each edge: vertex[upper] - vertex[lower] */
eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
/* compute area, oneOverArea and perform backface culling */
{
const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
if (util_is_inf_or_nan(area) || area == 0.0F)
return;
if (area * bf * swrast->_BackfaceCullSign < 0.0F)
return;
oneOverArea = 1.0F / area;
/* 0 = front, 1 = back */
span.facing = oneOverArea * bf > 0.0F;
}
/* Edge setup. For a triangle strip these could be reused... */
{
eMaj.fsy = FixedCeil(vMin_fy);
eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
if (eMaj.lines > 0) {
eMaj.dxdy = eMaj.dx / eMaj.dy;
eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy);
eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy); /* SCALED! */
eMaj.fx0 = vMin_fx;
eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy);
}
else {
return; /*CULLED*/
}
eTop.fsy = FixedCeil(vMid_fy);
eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
if (eTop.lines > 0) {
eTop.dxdy = eTop.dx / eTop.dy;
eTop.fdxdy = SignedFloatToFixed(eTop.dxdy);
eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
eTop.fx0 = vMid_fx;
eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy);
}
eBot.fsy = FixedCeil(vMin_fy);
eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
if (eBot.lines > 0) {
eBot.dxdy = eBot.dx / eBot.dy;
eBot.fdxdy = SignedFloatToFixed(eBot.dxdy);
eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy); /* SCALED! */
eBot.fx0 = vMin_fx;
eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy);
}
}
/*
* Conceptually, we view a triangle as two subtriangles
* separated by a perfectly horizontal line. The edge that is
* intersected by this line is one with maximal absolute dy; we
* call it a ``major'' edge. The other two edges are the
* ``top'' edge (for the upper subtriangle) and the ``bottom''
* edge (for the lower subtriangle). If either of these two
* edges is horizontal or very close to horizontal, the
* corresponding subtriangle might cover zero sample points;
* we take care to handle such cases, for performance as well
* as correctness.
*
* By stepping rasterization parameters along the major edge,
* we can avoid recomputing them at the discontinuity where
* the top and bottom edges meet. However, this forces us to
* be able to scan both left-to-right and right-to-left.
* Also, we must determine whether the major edge is at the
* left or right side of the triangle. We do this by
* computing the magnitude of the cross-product of the major
* and top edges. Since this magnitude depends on the sine of
* the angle between the two edges, its sign tells us whether
* we turn to the left or to the right when travelling along
* the major edge to the top edge, and from this we infer
* whether the major edge is on the left or the right.
*
* Serendipitously, this cross-product magnitude is also a
* value we need to compute the iteration parameter
* derivatives for the triangle, and it can be used to perform
* backface culling because its sign tells us whether the
* triangle is clockwise or counterclockwise. In this code we
* refer to it as ``area'' because it's also proportional to
* the pixel area of the triangle.
*/
{
GLint scan_from_left_to_right; /* true if scanning left-to-right */
/*
* Execute user-supplied setup code
*/
#ifdef SETUP_CODE
SETUP_CODE
#endif
scan_from_left_to_right = (oneOverArea < 0.0F);
/* compute d?/dx and d?/dy derivatives */
#ifdef INTERP_Z
span.interpMask |= SPAN_Z;
{
GLfloat eMaj_dz = vMax->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2];
GLfloat eBot_dz = vMid->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2];
span.attrStepX[VARYING_SLOT_POS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
if (span.attrStepX[VARYING_SLOT_POS][2] > maxDepth ||
span.attrStepX[VARYING_SLOT_POS][2] < -maxDepth) {
/* probably a sliver triangle */
span.attrStepX[VARYING_SLOT_POS][2] = 0.0;
span.attrStepY[VARYING_SLOT_POS][2] = 0.0;
}
else {
span.attrStepY[VARYING_SLOT_POS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
}
if (depthBits <= 16)
span.zStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_POS][2]);
else
span.zStep = (GLint) span.attrStepX[VARYING_SLOT_POS][2];
}
#endif
#ifdef INTERP_RGB
span.interpMask |= SPAN_RGBA;
if (ctx->Light.ShadeModel == GL_SMOOTH) {
GLfloat eMaj_dr = (GLfloat) (vMax->color[RCOMP] - vMin->color[RCOMP]);
GLfloat eBot_dr = (GLfloat) (vMid->color[RCOMP] - vMin->color[RCOMP]);
GLfloat eMaj_dg = (GLfloat) (vMax->color[GCOMP] - vMin->color[GCOMP]);
GLfloat eBot_dg = (GLfloat) (vMid->color[GCOMP] - vMin->color[GCOMP]);
GLfloat eMaj_db = (GLfloat) (vMax->color[BCOMP] - vMin->color[BCOMP]);
GLfloat eBot_db = (GLfloat) (vMid->color[BCOMP] - vMin->color[BCOMP]);
# ifdef INTERP_ALPHA
GLfloat eMaj_da = (GLfloat) (vMax->color[ACOMP] - vMin->color[ACOMP]);
GLfloat eBot_da = (GLfloat) (vMid->color[ACOMP] - vMin->color[ACOMP]);
# endif
span.attrStepX[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
span.attrStepY[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
span.attrStepX[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
span.attrStepY[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
span.attrStepX[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
span.attrStepY[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
span.redStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][0]);
span.greenStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][1]);
span.blueStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][2]);
# ifdef INTERP_ALPHA
span.attrStepX[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
span.attrStepY[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
span.alphaStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][3]);
# endif /* INTERP_ALPHA */
}
else {
assert(ctx->Light.ShadeModel == GL_FLAT);
span.interpMask |= SPAN_FLAT;
span.attrStepX[VARYING_SLOT_COL0][0] = span.attrStepY[VARYING_SLOT_COL0][0] = 0.0F;
span.attrStepX[VARYING_SLOT_COL0][1] = span.attrStepY[VARYING_SLOT_COL0][1] = 0.0F;
span.attrStepX[VARYING_SLOT_COL0][2] = span.attrStepY[VARYING_SLOT_COL0][2] = 0.0F;
span.redStep = 0;
span.greenStep = 0;
span.blueStep = 0;
# ifdef INTERP_ALPHA
span.attrStepX[VARYING_SLOT_COL0][3] = span.attrStepY[VARYING_SLOT_COL0][3] = 0.0F;
span.alphaStep = 0;
# endif
}
#endif /* INTERP_RGB */
#ifdef INTERP_INT_TEX
{
GLfloat eMaj_ds = (vMax->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE;
GLfloat eBot_ds = (vMid->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE;
GLfloat eMaj_dt = (vMax->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE;
GLfloat eBot_dt = (vMid->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE;
span.attrStepX[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
span.attrStepY[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
span.attrStepX[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
span.attrStepY[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][0]);
span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][1]);
}
#endif
#ifdef INTERP_ATTRIBS
{
/* attrib[VARYING_SLOT_POS][3] is 1/W */
const GLfloat wMax = vMax->attrib[VARYING_SLOT_POS][3];
const GLfloat wMin = vMin->attrib[VARYING_SLOT_POS][3];
const GLfloat wMid = vMid->attrib[VARYING_SLOT_POS][3];
{
const GLfloat eMaj_dw = wMax - wMin;
const GLfloat eBot_dw = wMid - wMin;
span.attrStepX[VARYING_SLOT_POS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw);
span.attrStepY[VARYING_SLOT_POS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx);
}
ATTRIB_LOOP_BEGIN
if (swrast->_InterpMode[attr] == GL_FLAT) {
ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
}
else {
GLuint c;
for (c = 0; c < 4; c++) {
GLfloat eMaj_da = vMax->attrib[attr][c] * wMax - vMin->attrib[attr][c] * wMin;
GLfloat eBot_da = vMid->attrib[attr][c] * wMid - vMin->attrib[attr][c] * wMin;
span.attrStepX[attr][c] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
span.attrStepY[attr][c] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
}
}
ATTRIB_LOOP_END
}
#endif
/*
* We always sample at pixel centers. However, we avoid
* explicit half-pixel offsets in this code by incorporating
* the proper offset in each of x and y during the
* transformation to window coordinates.
*
* We also apply the usual rasterization rules to prevent
* cracks and overlaps. A pixel is considered inside a
* subtriangle if it meets all of four conditions: it is on or
* to the right of the left edge, strictly to the left of the
* right edge, on or below the top edge, and strictly above
* the bottom edge. (Some edges may be degenerate.)
*
* The following discussion assumes left-to-right scanning
* (that is, the major edge is on the left); the right-to-left
* case is a straightforward variation.
*
* We start by finding the half-integral y coordinate that is
* at or below the top of the triangle. This gives us the
* first scan line that could possibly contain pixels that are
* inside the triangle.
*
* Next we creep down the major edge until we reach that y,
* and compute the corresponding x coordinate on the edge.
* Then we find the half-integral x that lies on or just
* inside the edge. This is the first pixel that might lie in
* the interior of the triangle. (We won't know for sure
* until we check the other edges.)
*
* As we rasterize the triangle, we'll step down the major
* edge. For each step in y, we'll move an integer number
* of steps in x. There are two possible x step sizes, which
* we'll call the ``inner'' step (guaranteed to land on the
* edge or inside it) and the ``outer'' step (guaranteed to
* land on the edge or outside it). The inner and outer steps
* differ by one. During rasterization we maintain an error
* term that indicates our distance from the true edge, and
* select either the inner step or the outer step, whichever
* gets us to the first pixel that falls inside the triangle.
*
* All parameters (z, red, etc.) as well as the buffer
* addresses for color and z have inner and outer step values,
* so that we can increment them appropriately. This method
* eliminates the need to adjust parameters by creeping a
* sub-pixel amount into the triangle at each scanline.
*/
{
GLint subTriangle;
GLfixed fxLeftEdge = 0, fxRightEdge = 0;
GLfixed fdxLeftEdge = 0, fdxRightEdge = 0;
GLfixed fError = 0, fdError = 0;
#ifdef PIXEL_ADDRESS
PIXEL_TYPE *pRow = NULL;
GLint dPRowOuter = 0, dPRowInner; /* offset in bytes */
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
struct gl_renderbuffer *zrb
= ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
DEPTH_TYPE *zRow = NULL;
GLint dZRowOuter = 0, dZRowInner; /* offset in bytes */
# endif
GLuint zLeft = 0;
GLfixed fdzOuter = 0, fdzInner;
#endif
#ifdef INTERP_RGB
GLint rLeft = 0, fdrOuter = 0, fdrInner;
GLint gLeft = 0, fdgOuter = 0, fdgInner;
GLint bLeft = 0, fdbOuter = 0, fdbInner;
#endif
#ifdef INTERP_ALPHA
GLint aLeft = 0, fdaOuter = 0, fdaInner;
#endif
#ifdef INTERP_INT_TEX
GLfixed sLeft=0, dsOuter=0, dsInner;
GLfixed tLeft=0, dtOuter=0, dtInner;
#endif
#ifdef INTERP_ATTRIBS
GLfloat wLeft = 0, dwOuter = 0, dwInner;
GLfloat attrLeft[VARYING_SLOT_MAX][4];
GLfloat daOuter[VARYING_SLOT_MAX][4], daInner[VARYING_SLOT_MAX][4];
#endif
for (subTriangle=0; subTriangle<=1; subTriangle++) {
EdgeT *eLeft, *eRight;
int setupLeft, setupRight;
int lines;
if (subTriangle==0) {
/* bottom half */
if (scan_from_left_to_right) {
eLeft = &eMaj;
eRight = &eBot;
lines = eRight->lines;
setupLeft = 1;
setupRight = 1;
}
else {
eLeft = &eBot;
eRight = &eMaj;
lines = eLeft->lines;
setupLeft = 1;
setupRight = 1;
}
}
else {
/* top half */
if (scan_from_left_to_right) {
eLeft = &eMaj;
eRight = &eTop;
lines = eRight->lines;
setupLeft = 0;
setupRight = 1;
}
else {
eLeft = &eTop;
eRight = &eMaj;
lines = eLeft->lines;
setupLeft = 1;
setupRight = 0;
}
if (lines == 0)
return;
}
if (setupLeft && eLeft->lines > 0) {
const SWvertex *vLower = eLeft->v0;
const GLfixed fsy = eLeft->fsy;
const GLfixed fsx = eLeft->fsx; /* no fractional part */
const GLfixed fx = FixedCeil(fsx); /* no fractional part */
const GLfixed adjx = (GLfixed) (fx - eLeft->fx0); /* SCALED! */
const GLfixed adjy = (GLfixed) eLeft->adjy; /* SCALED! */
GLint idxOuter;
GLfloat dxOuter;
GLfixed fdxOuter;
fError = fx - fsx - FIXED_ONE;
fxLeftEdge = fsx - FIXED_EPSILON;
fdxLeftEdge = eLeft->fdxdy;
fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
idxOuter = FixedToInt(fdxOuter);
dxOuter = (GLfloat) idxOuter;
span.y = FixedToInt(fsy);
/* silence warnings on some compilers */
(void) dxOuter;
(void) adjx;
(void) adjy;
(void) vLower;
#ifdef PIXEL_ADDRESS
{
pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y);
dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
/* negative because Y=0 at bottom and increases upward */
}
#endif
/*
* Now we need the set of parameter (z, color, etc.) values at
* the point (fx, fsy). This gives us properly-sampled parameter
* values that we can step from pixel to pixel. Furthermore,
* although we might have intermediate results that overflow
* the normal parameter range when we step temporarily outside
* the triangle, we shouldn't overflow or underflow for any
* pixel that's actually inside the triangle.
*/
#ifdef INTERP_Z
{
GLfloat z0 = vLower->attrib[VARYING_SLOT_POS][2];
if (depthBits <= 16) {
/* interpolate fixed-pt values */
GLfloat tmp = (z0 * FIXED_SCALE
+ span.attrStepX[VARYING_SLOT_POS][2] * adjx
+ span.attrStepY[VARYING_SLOT_POS][2] * adjy) + FIXED_HALF;
if (tmp < MAX_GLUINT / 2)
zLeft = (GLfixed) tmp;
else
zLeft = MAX_GLUINT / 2;
fdzOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_POS][2] +
dxOuter * span.attrStepX[VARYING_SLOT_POS][2]);
}
else {
/* interpolate depth values w/out scaling */
zLeft = (GLuint) (z0 + span.attrStepX[VARYING_SLOT_POS][2] * FixedToFloat(adjx)
+ span.attrStepY[VARYING_SLOT_POS][2] * FixedToFloat(adjy));
fdzOuter = (GLint) (span.attrStepY[VARYING_SLOT_POS][2] +
dxOuter * span.attrStepX[VARYING_SLOT_POS][2]);
}
# ifdef DEPTH_TYPE
zRow = (DEPTH_TYPE *)
_swrast_pixel_address(zrb, FixedToInt(fxLeftEdge), span.y);
dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
# endif
}
#endif
#ifdef INTERP_RGB
if (ctx->Light.ShadeModel == GL_SMOOTH) {
rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP])
+ span.attrStepX[VARYING_SLOT_COL0][0] * adjx
+ span.attrStepY[VARYING_SLOT_COL0][0] * adjy) + FIXED_HALF;
gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP])
+ span.attrStepX[VARYING_SLOT_COL0][1] * adjx
+ span.attrStepY[VARYING_SLOT_COL0][1] * adjy) + FIXED_HALF;
bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP])
+ span.attrStepX[VARYING_SLOT_COL0][2] * adjx
+ span.attrStepY[VARYING_SLOT_COL0][2] * adjy) + FIXED_HALF;
fdrOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][0]
+ dxOuter * span.attrStepX[VARYING_SLOT_COL0][0]);
fdgOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][1]
+ dxOuter * span.attrStepX[VARYING_SLOT_COL0][1]);
fdbOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][2]
+ dxOuter * span.attrStepX[VARYING_SLOT_COL0][2]);
# ifdef INTERP_ALPHA
aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP])
+ span.attrStepX[VARYING_SLOT_COL0][3] * adjx
+ span.attrStepY[VARYING_SLOT_COL0][3] * adjy) + FIXED_HALF;
fdaOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][3]
+ dxOuter * span.attrStepX[VARYING_SLOT_COL0][3]);
# endif
}
else {
assert(ctx->Light.ShadeModel == GL_FLAT);
rLeft = ChanToFixed(v2->color[RCOMP]);
gLeft = ChanToFixed(v2->color[GCOMP]);
bLeft = ChanToFixed(v2->color[BCOMP]);
fdrOuter = fdgOuter = fdbOuter = 0;
# ifdef INTERP_ALPHA
aLeft = ChanToFixed(v2->color[ACOMP]);
fdaOuter = 0;
# endif
}
#endif /* INTERP_RGB */
#ifdef INTERP_INT_TEX
{
GLfloat s0, t0;
s0 = vLower->attrib[VARYING_SLOT_TEX0][0] * S_SCALE;
sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][0] * adjx
+ span.attrStepY[VARYING_SLOT_TEX0][0] * adjy) + FIXED_HALF;
dsOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][0]
+ dxOuter * span.attrStepX[VARYING_SLOT_TEX0][0]);
t0 = vLower->attrib[VARYING_SLOT_TEX0][1] * T_SCALE;
tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][1] * adjx
+ span.attrStepY[VARYING_SLOT_TEX0][1] * adjy) + FIXED_HALF;
dtOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][1]
+ dxOuter * span.attrStepX[VARYING_SLOT_TEX0][1]);
}
#endif
#ifdef INTERP_ATTRIBS
{
const GLuint attr = VARYING_SLOT_POS;
wLeft = vLower->attrib[VARYING_SLOT_POS][3]
+ (span.attrStepX[attr][3] * adjx
+ span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE);
dwOuter = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3];
}
ATTRIB_LOOP_BEGIN
const GLfloat invW = vLower->attrib[VARYING_SLOT_POS][3];
if (swrast->_InterpMode[attr] == GL_FLAT) {
GLuint c;
for (c = 0; c < 4; c++) {
attrLeft[attr][c] = v2->attrib[attr][c] * invW;
daOuter[attr][c] = 0.0;
}
}
else {
GLuint c;
for (c = 0; c < 4; c++) {
const GLfloat a = vLower->attrib[attr][c] * invW;
attrLeft[attr][c] = a + ( span.attrStepX[attr][c] * adjx
+ span.attrStepY[attr][c] * adjy) * (1.0F/FIXED_SCALE);
daOuter[attr][c] = span.attrStepY[attr][c] + dxOuter * span.attrStepX[attr][c];
}
}
ATTRIB_LOOP_END
#endif
} /*if setupLeft*/
if (setupRight && eRight->lines>0) {
fxRightEdge = eRight->fsx - FIXED_EPSILON;
fdxRightEdge = eRight->fdxdy;
}
if (lines==0) {
continue;
}
/* Rasterize setup */
#ifdef PIXEL_ADDRESS
dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
# endif
fdzInner = fdzOuter + span.zStep;
#endif
#ifdef INTERP_RGB
fdrInner = fdrOuter + span.redStep;
fdgInner = fdgOuter + span.greenStep;
fdbInner = fdbOuter + span.blueStep;
#endif
#ifdef INTERP_ALPHA
fdaInner = fdaOuter + span.alphaStep;
#endif
#ifdef INTERP_INT_TEX
dsInner = dsOuter + span.intTexStep[0];
dtInner = dtOuter + span.intTexStep[1];
#endif
#ifdef INTERP_ATTRIBS
dwInner = dwOuter + span.attrStepX[VARYING_SLOT_POS][3];
ATTRIB_LOOP_BEGIN
GLuint c;
for (c = 0; c < 4; c++) {
daInner[attr][c] = daOuter[attr][c] + span.attrStepX[attr][c];
}
ATTRIB_LOOP_END
#endif
while (lines > 0) {
/* initialize the span interpolants to the leftmost value */
/* ff = fixed-pt fragment */
const GLint right = FixedToInt(fxRightEdge);
span.x = FixedToInt(fxLeftEdge);
if (right <= span.x)
span.end = 0;
else
span.end = right - span.x;
#ifdef INTERP_Z
span.z = zLeft;
#endif
#ifdef INTERP_RGB
span.red = rLeft;
span.green = gLeft;
span.blue = bLeft;
#endif
#ifdef INTERP_ALPHA
span.alpha = aLeft;
#endif
#ifdef INTERP_INT_TEX
span.intTex[0] = sLeft;
span.intTex[1] = tLeft;
#endif
#ifdef INTERP_ATTRIBS
span.attrStart[VARYING_SLOT_POS][3] = wLeft;
ATTRIB_LOOP_BEGIN
GLuint c;
for (c = 0; c < 4; c++) {
span.attrStart[attr][c] = attrLeft[attr][c];
}
ATTRIB_LOOP_END
#endif
/* This is where we actually generate fragments */
/* XXX the test for span.y > 0 _shouldn't_ be needed but
* it fixes a problem on 64-bit Opterons (bug 4842).
*/
if (span.end > 0 && span.y >= 0) {
const GLint len = span.end - 1;
(void) len;
#ifdef INTERP_RGB
CLAMP_INTERPOLANT(red, redStep, len);
CLAMP_INTERPOLANT(green, greenStep, len);
CLAMP_INTERPOLANT(blue, blueStep, len);
#endif
#ifdef INTERP_ALPHA
CLAMP_INTERPOLANT(alpha, alphaStep, len);
#endif
{
RENDER_SPAN( span );
}
}
/*
* Advance to the next scan line. Compute the
* new edge coordinates, and adjust the
* pixel-center x coordinate so that it stays
* on or inside the major edge.
*/
span.y++;
lines--;
fxLeftEdge += fdxLeftEdge;
fxRightEdge += fdxRightEdge;
fError += fdError;
if (fError >= 0) {
fError -= FIXED_ONE;
#ifdef PIXEL_ADDRESS
pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
# endif
zLeft += fdzOuter;
#endif
#ifdef INTERP_RGB
rLeft += fdrOuter;
gLeft += fdgOuter;
bLeft += fdbOuter;
#endif
#ifdef INTERP_ALPHA
aLeft += fdaOuter;
#endif
#ifdef INTERP_INT_TEX
sLeft += dsOuter;
tLeft += dtOuter;
#endif
#ifdef INTERP_ATTRIBS
wLeft += dwOuter;
ATTRIB_LOOP_BEGIN
GLuint c;
for (c = 0; c < 4; c++) {
attrLeft[attr][c] += daOuter[attr][c];
}
ATTRIB_LOOP_END
#endif
}
else {
#ifdef PIXEL_ADDRESS
pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
#endif
#ifdef INTERP_Z
# ifdef DEPTH_TYPE
zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
# endif
zLeft += fdzInner;
#endif
#ifdef INTERP_RGB
rLeft += fdrInner;
gLeft += fdgInner;
bLeft += fdbInner;
#endif
#ifdef INTERP_ALPHA
aLeft += fdaInner;
#endif
#ifdef INTERP_INT_TEX
sLeft += dsInner;
tLeft += dtInner;
#endif
#ifdef INTERP_ATTRIBS
wLeft += dwInner;
ATTRIB_LOOP_BEGIN
GLuint c;
for (c = 0; c < 4; c++) {
attrLeft[attr][c] += daInner[attr][c];
}
ATTRIB_LOOP_END
#endif
}
} /*while lines>0*/
} /* for subTriangle */
}
}
}
#undef SETUP_CODE
#undef RENDER_SPAN
#undef PIXEL_TYPE
#undef BYTES_PER_ROW
#undef PIXEL_ADDRESS
#undef DEPTH_TYPE
#undef INTERP_Z
#undef INTERP_RGB
#undef INTERP_ALPHA
#undef INTERP_INT_TEX
#undef INTERP_ATTRIBS
#undef S_SCALE
#undef T_SCALE
#undef FixedToDepth
#undef NAME

View File

@ -1,442 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/errors.h"
#include "main/glheader.h"
#include "main/macros.h"
#include "main/format_pack.h"
#include "s_context.h"
#include "s_span.h"
#include "s_stencil.h"
#include "s_zoom.h"
/**
* Compute the bounds of the region resulting from zooming a pixel span.
* The resulting region will be entirely inside the window/scissor bounds
* so no additional clipping is needed.
* \param imageX, imageY position of the mage being drawn (gl WindowPos)
* \param spanX, spanY position of span being drawing
* \param width number of pixels in span
* \param x0, x1 returned X bounds of zoomed region [x0, x1)
* \param y0, y1 returned Y bounds of zoomed region [y0, y1)
* \return GL_TRUE if any zoomed pixels visible, GL_FALSE if totally clipped
*/
static GLboolean
compute_zoomed_bounds(struct gl_context *ctx, GLint imageX, GLint imageY,
GLint spanX, GLint spanY, GLint width,
GLint *x0, GLint *x1, GLint *y0, GLint *y1)
{
const struct gl_framebuffer *fb = ctx->DrawBuffer;
GLint c0, c1, r0, r1;
assert(spanX >= imageX);
assert(spanY >= imageY);
/*
* Compute destination columns: [c0, c1)
*/
c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX);
c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX);
if (c1 < c0) {
/* swap */
GLint tmp = c1;
c1 = c0;
c0 = tmp;
}
c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax);
c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax);
if (c0 == c1) {
return GL_FALSE; /* no width */
}
/*
* Compute destination rows: [r0, r1)
*/
r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY);
r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY);
if (r1 < r0) {
/* swap */
GLint tmp = r1;
r1 = r0;
r0 = tmp;
}
r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax);
r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax);
if (r0 == r1) {
return GL_FALSE; /* no height */
}
*x0 = c0;
*x1 = c1;
*y0 = r0;
*y1 = r1;
return GL_TRUE;
}
/**
* Convert a zoomed x image coordinate back to an unzoomed x coord.
* 'zx' is screen position of a pixel in the zoomed image, who's left edge
* is at 'imageX'.
* return corresponding x coord in the original, unzoomed image.
* This can use this for unzooming X or Y values.
*/
static inline GLint
unzoom_x(GLfloat zoomX, GLint imageX, GLint zx)
{
/*
zx = imageX + (x - imageX) * zoomX;
zx - imageX = (x - imageX) * zoomX;
(zx - imageX) / zoomX = x - imageX;
*/
GLint x;
if (zoomX < 0.0F)
zx++;
x = imageX + (GLint) ((zx - imageX) / zoomX);
return x;
}
/**
* Helper function called from _swrast_write_zoomed_rgba/rgb/
* index/depth_span().
*/
static void
zoom_span( struct gl_context *ctx, GLint imgX, GLint imgY, const SWspan *span,
const GLvoid *src, GLenum format )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
SWspan zoomed;
GLint x0, x1, y0, y1;
GLint zoomedWidth;
if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end,
&x0, &x1, &y0, &y1)) {
return; /* totally clipped */
}
if (!swrast->ZoomedArrays) {
/* allocate on demand */
swrast->ZoomedArrays = (SWspanarrays *) calloc(1, sizeof(SWspanarrays));
if (!swrast->ZoomedArrays)
return;
}
zoomedWidth = x1 - x0;
assert(zoomedWidth > 0);
assert(zoomedWidth <= SWRAST_MAX_WIDTH);
/* no pixel arrays! must be horizontal spans. */
assert((span->arrayMask & SPAN_XY) == 0);
assert(span->primitive == GL_BITMAP);
INIT_SPAN(zoomed, GL_BITMAP);
zoomed.x = x0;
zoomed.end = zoomedWidth;
zoomed.array = swrast->ZoomedArrays;
zoomed.array->ChanType = span->array->ChanType;
if (zoomed.array->ChanType == GL_UNSIGNED_BYTE)
zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8;
else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT)
zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16;
else
zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[VARYING_SLOT_COL0];
COPY_4V(zoomed.attrStart[VARYING_SLOT_POS], span->attrStart[VARYING_SLOT_POS]);
COPY_4V(zoomed.attrStepX[VARYING_SLOT_POS], span->attrStepX[VARYING_SLOT_POS]);
COPY_4V(zoomed.attrStepY[VARYING_SLOT_POS], span->attrStepY[VARYING_SLOT_POS]);
zoomed.attrStart[VARYING_SLOT_FOGC][0] = span->attrStart[VARYING_SLOT_FOGC][0];
zoomed.attrStepX[VARYING_SLOT_FOGC][0] = span->attrStepX[VARYING_SLOT_FOGC][0];
zoomed.attrStepY[VARYING_SLOT_FOGC][0] = span->attrStepY[VARYING_SLOT_FOGC][0];
if (format == GL_RGBA || format == GL_RGB) {
/* copy Z info */
zoomed.z = span->z;
zoomed.zStep = span->zStep;
/* we'll generate an array of colorss */
zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
zoomed.arrayMask |= SPAN_RGBA;
zoomed.arrayAttribs |= VARYING_BIT_COL0; /* we'll produce these values */
assert(span->arrayMask & SPAN_RGBA);
}
else if (format == GL_DEPTH_COMPONENT) {
/* Copy color info */
zoomed.red = span->red;
zoomed.green = span->green;
zoomed.blue = span->blue;
zoomed.alpha = span->alpha;
zoomed.redStep = span->redStep;
zoomed.greenStep = span->greenStep;
zoomed.blueStep = span->blueStep;
zoomed.alphaStep = span->alphaStep;
/* we'll generate an array of depth values */
zoomed.interpMask = span->interpMask & ~SPAN_Z;
zoomed.arrayMask |= SPAN_Z;
assert(span->arrayMask & SPAN_Z);
}
else {
_mesa_problem(ctx, "Bad format in zoom_span");
return;
}
/* zoom the span horizontally */
if (format == GL_RGBA) {
if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
assert(j >= 0);
assert(j < (GLint) span->end);
COPY_4UBV(zoomed.array->rgba8[i], rgba[j]);
}
}
else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
const GLushort (*rgba)[4] = (const GLushort (*)[4]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
assert(j >= 0);
assert(j < (GLint) span->end);
COPY_4V(zoomed.array->rgba16[i], rgba[j]);
}
}
else {
const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
assert(j >= 0);
assert(j < (GLint) span->end);
COPY_4V(zoomed.array->attribs[VARYING_SLOT_COL0][i], rgba[j]);
}
}
}
else if (format == GL_RGB) {
if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
assert(j >= 0);
assert(j < (GLint) span->end);
zoomed.array->rgba8[i][0] = rgb[j][0];
zoomed.array->rgba8[i][1] = rgb[j][1];
zoomed.array->rgba8[i][2] = rgb[j][2];
zoomed.array->rgba8[i][3] = 0xff;
}
}
else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
const GLushort (*rgb)[3] = (const GLushort (*)[3]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
assert(j >= 0);
assert(j < (GLint) span->end);
zoomed.array->rgba16[i][0] = rgb[j][0];
zoomed.array->rgba16[i][1] = rgb[j][1];
zoomed.array->rgba16[i][2] = rgb[j][2];
zoomed.array->rgba16[i][3] = 0xffff;
}
}
else {
const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
assert(j >= 0);
assert(j < (GLint) span->end);
zoomed.array->attribs[VARYING_SLOT_COL0][i][0] = rgb[j][0];
zoomed.array->attribs[VARYING_SLOT_COL0][i][1] = rgb[j][1];
zoomed.array->attribs[VARYING_SLOT_COL0][i][2] = rgb[j][2];
zoomed.array->attribs[VARYING_SLOT_COL0][i][3] = 1.0F;
}
}
}
else if (format == GL_DEPTH_COMPONENT) {
const GLuint *zValues = (const GLuint *) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
assert(j >= 0);
assert(j < (GLint) span->end);
zoomed.array->z[i] = zValues[j];
}
/* Now, fall into the RGB path below */
format = GL_RGBA;
}
/* write the span in rows [r0, r1) */
if (format == GL_RGBA || format == GL_RGB) {
/* Writing the span may modify the colors, so make a backup now if we're
* going to call _swrast_write_zoomed_span() more than once.
* Also, clipping may change the span end value, so store it as well.
*/
const GLint end = zoomed.end; /* save */
void *rgbaSave;
const GLint pixelSize =
(zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) :
((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort)
: 4 * sizeof(GLfloat));
rgbaSave = malloc(zoomed.end * pixelSize);
if (!rgbaSave) {
return;
}
if (y1 - y0 > 1) {
memcpy(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize);
}
for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
_swrast_write_rgba_span(ctx, &zoomed);
zoomed.end = end; /* restore */
if (y1 - y0 > 1) {
/* restore the colors */
memcpy(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize);
}
}
free(rgbaSave);
}
}
void
_swrast_write_zoomed_rgba_span(struct gl_context *ctx, GLint imgX, GLint imgY,
const SWspan *span, const GLvoid *rgba)
{
zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA);
}
void
_swrast_write_zoomed_rgb_span(struct gl_context *ctx, GLint imgX, GLint imgY,
const SWspan *span, const GLvoid *rgb)
{
zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB);
}
void
_swrast_write_zoomed_depth_span(struct gl_context *ctx, GLint imgX, GLint imgY,
const SWspan *span)
{
zoom_span(ctx, imgX, imgY, span,
(const GLvoid *) span->array->z, GL_DEPTH_COMPONENT);
}
/**
* Zoom/write stencil values.
* No per-fragment operations are applied.
*/
void
_swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY,
GLint width, GLint spanX, GLint spanY,
const GLubyte stencil[])
{
GLubyte *zoomedVals;
GLint x0, x1, y0, y1, y;
GLint i, zoomedWidth;
if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
&x0, &x1, &y0, &y1)) {
return; /* totally clipped */
}
zoomedWidth = x1 - x0;
assert(zoomedWidth > 0);
assert(zoomedWidth <= SWRAST_MAX_WIDTH);
zoomedVals = malloc(zoomedWidth * sizeof(GLubyte));
if (!zoomedVals)
return;
/* zoom the span horizontally */
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
assert(j >= 0);
assert(j < width);
zoomedVals[i] = stencil[j];
}
/* write the zoomed spans */
for (y = y0; y < y1; y++) {
_swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals);
}
free(zoomedVals);
}
/**
* Zoom/write 32-bit Z values.
* No per-fragment operations are applied.
*/
void
_swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY,
GLint width, GLint spanX, GLint spanY,
const GLuint *zVals)
{
struct gl_renderbuffer *rb =
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
GLuint *zoomedVals;
GLint x0, x1, y0, y1, y;
GLint i, zoomedWidth;
if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
&x0, &x1, &y0, &y1)) {
return; /* totally clipped */
}
zoomedWidth = x1 - x0;
assert(zoomedWidth > 0);
assert(zoomedWidth <= SWRAST_MAX_WIDTH);
zoomedVals = malloc(zoomedWidth * sizeof(GLuint));
if (!zoomedVals)
return;
/* zoom the span horizontally */
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
assert(j >= 0);
assert(j < width);
zoomedVals[i] = zVals[j];
}
/* write the zoomed spans */
for (y = y0; y < y1; y++) {
GLubyte *dst = _swrast_pixel_address(rb, x0, y);
_mesa_pack_uint_z_row(rb->Format, zoomedWidth, zoomedVals, dst);
}
free(zoomedVals);
}

View File

@ -1,56 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef S_ZOOM_H
#define S_ZOOM_H
#include "main/mtypes.h"
#include "s_span.h"
extern void
_swrast_write_zoomed_rgba_span(struct gl_context *ctx, GLint imgX, GLint imgY,
const SWspan *span, const GLvoid *rgba);
extern void
_swrast_write_zoomed_rgb_span(struct gl_context *ctx, GLint imgX, GLint imgY,
const SWspan *span, const GLvoid *rgb);
extern void
_swrast_write_zoomed_depth_span(struct gl_context *ctx, GLint imgX, GLint imgY,
const SWspan *span);
extern void
_swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY,
GLint width, GLint spanX, GLint spanY,
const GLubyte stencil[]);
extern void
_swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY,
GLint width, GLint spanX, GLint spanY,
const GLuint *zVals);
#endif

View File

@ -1,301 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
/**
* \file swrast/swrast.h
* \brief Public interface to the software rasterization functions.
* \author Keith Whitwell <keithw@vmware.com>
*/
#ifndef SWRAST_H
#define SWRAST_H
#include "main/mtypes.h"
#include "swrast/s_chan.h"
/**
* If non-zero use GLdouble for walking triangle edges, for better accuracy.
*/
#define TRIANGLE_WALK_DOUBLE 0
/**
* Bits per depth buffer value (max is 32).
*/
#ifndef DEFAULT_SOFTWARE_DEPTH_BITS
#define DEFAULT_SOFTWARE_DEPTH_BITS 16
#endif
/** Depth buffer data type */
#if DEFAULT_SOFTWARE_DEPTH_BITS <= 16
#define DEFAULT_SOFTWARE_DEPTH_TYPE GLushort
#else
#define DEFAULT_SOFTWARE_DEPTH_TYPE GLuint
#endif
/**
* Max image/surface/texture size.
*/
#define SWRAST_MAX_WIDTH 16384
#define SWRAST_MAX_HEIGHT 16384
/**
* \struct SWvertex
* \brief Data-structure to handle vertices in the software rasterizer.
*
* The software rasterizer now uses this format for vertices. Thus a
* 'RasterSetup' stage or other translation is required between the
* tnl module and the swrast rasterization functions. This serves to
* isolate the swrast module from the internals of the tnl module, and
* improve its usefulness as a fallback mechanism for hardware
* drivers.
*
* wpos = attr[VARYING_SLOT_POS] and MUST BE THE FIRST values in the
* vertex because of the tnl clipping code.
* wpos[0] and [1] are the screen-coords of SWvertex.
* wpos[2] is the z-buffer coord (if 16-bit Z buffer, in range [0,65535]).
* wpos[3] is 1/w where w is the clip-space W coord. This is the value
* that clip{XYZ} were multiplied by to get ndc{XYZ}.
*
* Full software drivers:
* - Register the rastersetup and triangle functions from
* utils/software_helper.
* - On statechange, update the rasterization pointers in that module.
*
* Rasterization hardware drivers:
* - Keep native rastersetup.
* - Implement native twoside,offset and unfilled triangle setup.
* - Implement a translator from native vertices to swrast vertices.
* - On partial fallback (mix of accelerated and unaccelerated
* prims), call a pass-through function which translates native
* vertices to SWvertices and calls the appropriate swrast function.
* - On total fallback (vertex format insufficient for state or all
* primitives unaccelerated), hook in swrast_setup instead.
*/
typedef struct {
GLfloat attrib[VARYING_SLOT_MAX][4];
GLchan color[4]; /** integer color */
GLfloat pointSize;
} SWvertex;
#define VARYING_SLOT_CI VARYING_SLOT_COL0
struct swrast_device_driver;
/* These are the public-access functions exported from swrast.
*/
extern GLboolean
_swrast_CreateContext( struct gl_context *ctx );
extern void
_swrast_DestroyContext( struct gl_context *ctx );
/* Get a (non-const) reference to the device driver struct for swrast.
*/
extern struct swrast_device_driver *
_swrast_GetDeviceDriverReference( struct gl_context *ctx );
extern void
_swrast_Bitmap( struct gl_context *ctx,
GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap );
extern void
_swrast_CopyPixels(struct gl_context *ctx,
GLint srcx, GLint srcy,
GLint destx, GLint desty,
GLsizei width, GLsizei height,
GLenum type);
extern GLboolean
swrast_fast_copy_pixels(struct gl_context *ctx,
struct gl_framebuffer *srcFb,
struct gl_framebuffer *dstFb,
GLint srcX, GLint srcY, GLsizei width, GLsizei height,
GLint dstX, GLint dstY, GLenum type);
extern void
_swrast_DrawPixels( struct gl_context *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );
extern void
_swrast_BlitFramebuffer(struct gl_context *ctx,
struct gl_framebuffer *readFb,
struct gl_framebuffer *drawFb,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
extern void
_swrast_Clear(struct gl_context *ctx, GLbitfield buffers);
/* Reset the stipple counter
*/
extern void
_swrast_ResetLineStipple( struct gl_context *ctx );
/**
* Indicates front/back facing for subsequent points/lines when drawing
* unfilled polygons. Needed for two-side stencil.
*/
extern void
_swrast_SetFacing(struct gl_context *ctx, GLuint facing);
/* These will always render the correct point/line/triangle for the
* current state.
*
* For flatshaded primitives, the provoking vertex is the final one.
*/
extern void
_swrast_Point( struct gl_context *ctx, const SWvertex *v );
extern void
_swrast_Line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 );
extern void
_swrast_Triangle( struct gl_context *ctx, const SWvertex *v0,
const SWvertex *v1, const SWvertex *v2 );
extern void
_swrast_Quad( struct gl_context *ctx,
const SWvertex *v0, const SWvertex *v1,
const SWvertex *v2, const SWvertex *v3);
extern void
_swrast_flush( struct gl_context *ctx );
extern void
_swrast_render_primitive( struct gl_context *ctx, GLenum mode );
extern void
_swrast_render_start( struct gl_context *ctx );
extern void
_swrast_render_finish( struct gl_context *ctx );
extern struct gl_texture_image *
_swrast_new_texture_image( struct gl_context *ctx );
extern void
_swrast_delete_texture_image(struct gl_context *ctx,
struct gl_texture_image *texImage);
extern GLboolean
_swrast_alloc_texture_image_buffer(struct gl_context *ctx,
struct gl_texture_image *texImage);
extern GLboolean
_swrast_init_texture_image(struct gl_texture_image *texImage);
extern void
_swrast_free_texture_image_buffer(struct gl_context *ctx,
struct gl_texture_image *texImage);
extern void
_swrast_map_teximage(struct gl_context *ctx,
struct gl_texture_image *texImage,
GLuint slice,
GLuint x, GLuint y, GLuint w, GLuint h,
GLbitfield mode,
GLubyte **mapOut,
GLint *rowStrideOut);
extern void
_swrast_unmap_teximage(struct gl_context *ctx,
struct gl_texture_image *texImage,
GLuint slice);
/* Tell the software rasterizer about core state changes.
*/
extern void
_swrast_InvalidateState( struct gl_context *ctx, GLbitfield new_state );
/* Configure software rasterizer to match hardware rasterizer characteristics:
*/
extern void
_swrast_allow_vertex_fog( struct gl_context *ctx, GLboolean value );
extern void
_swrast_allow_pixel_fog( struct gl_context *ctx, GLboolean value );
/* Debug:
*/
extern void
_swrast_print_vertex( struct gl_context *ctx, const SWvertex *v );
extern void
_swrast_eject_texture_images(struct gl_context *ctx);
extern void
_swrast_render_texture(struct gl_context *ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att);
extern void
_swrast_finish_render_texture(struct gl_context *ctx,
struct gl_renderbuffer *rb);
/**
* The driver interface for the software rasterizer.
* XXX this may go away.
* We may move these functions to ctx->Driver.RenderStart, RenderEnd.
*/
struct swrast_device_driver {
/*
* These are called before and after accessing renderbuffers during
* software rasterization.
*
* These are a suitable place for grabbing/releasing hardware locks.
*
* NOTE: The swrast triangle/line/point routines *DO NOT* call
* these functions. Locking in that case must be organized by the
* driver by other mechanisms.
*/
void (*SpanRenderStart)(struct gl_context *ctx);
void (*SpanRenderFinish)(struct gl_context *ctx);
};
#endif

View File

@ -1,65 +0,0 @@
INTRODUCTION
A helper module which provides glue to bind the software rasterizer to
the software t&l module. The main task of this module is to build
swrast vertices from the t&l vertex_buffer structs, and to use them to
perform triangle setup functions not implemented in the software
rasterizer.
The module implements a full set of functions to plug into the
t_vb_render.c driver interface (tnl->Driver.Render.*).
There are strong advantages to decoupling the software rasterizer from
the t&l module, primarily allowing hardware drivers better control
over fallbacks, the removal of implicit knowledge about the software
rasterizer in the t&l module, allowing the two modules to evolve
independently and allowing either to be substituted with equivalent
functionality from another codebase.
This module implements triangle/quad setup for offset, unfilled and
twoside-lit triangles. The software rasterizer doesn't handle these
primitives directly.
Hardware rasterization drivers typically use this module in situations
where no hardware rasterization is possible, ie during total
fallbacks.
STATE
To create and destroy the module:
GLboolean _swsetup_CreateContext( struct gl_context *ctx );
void _swsetup_DestroyContext( struct gl_context *ctx );
The module is not active by default, and must be installed by calling
_swrast_Wakeup(). This function installs internal swrast_setup
functions into all the tnl->Driver.Render driver hooks, thus taking
over the task of rasterization entirely:
void _swrast_Wakeup( struct gl_context *ctx );
This module tracks state changes internally and maintains derived
values based on the current state. For this to work, the driver
ensure the following funciton is called whenever the state changes and
the swsetup module is 'awake':
void _swsetup_InvalidateState( struct gl_context *ctx, GLuint new_state );
There is no explicit call to put the swsetup module to sleep. Simply
install other function pointers into all the tnl->Driver.Render.*
hooks, and (optionally) cease calling _swsetup_InvalidateState().
DRIVER INTERFACE
The module offers a minimal driver interface:
void (*Start)( struct gl_context *ctx );
void (*Finish)( struct gl_context *ctx );
These are called before and after the completion of all swrast drawing
activity. As swrast doesn't call callbacks during triangle, line or
point rasterization, these are necessary to provide locking hooks for
some drivers. They may otherwise be left null.

View File

@ -1,305 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "main/glheader.h"
#include "main/macros.h"
#include "main/state.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "tnl/t_pipeline.h"
#include "tnl/t_vertex.h"
#include "swrast_setup.h"
#include "ss_context.h"
#include "ss_triangle.h"
/* Need to check lighting state and vertex program state to know
* if two-sided lighting is in effect.
*/
#define _SWSETUP_NEW_RENDERINDEX (_NEW_POLYGON|_NEW_LIGHT|_NEW_PROGRAM)
#define VARYING_EMIT_STYLE EMIT_4F
GLboolean
_swsetup_CreateContext( struct gl_context *ctx )
{
SScontext *swsetup = calloc(1, sizeof(SScontext));
if (!swsetup)
return GL_FALSE;
ctx->swsetup_context = swsetup;
swsetup->NewState = ~0;
_swsetup_trifuncs_init( ctx );
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
sizeof(SWvertex) );
return GL_TRUE;
}
void
_swsetup_DestroyContext( struct gl_context *ctx )
{
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
if (swsetup) {
free(swsetup);
ctx->swsetup_context = 0;
}
_tnl_free_vertices( ctx );
}
static void
_swsetup_RenderPrimitive( struct gl_context *ctx, GLenum mode )
{
SWSETUP_CONTEXT(ctx)->render_prim = mode;
_swrast_render_primitive( ctx, mode );
}
/**
* Helper macros for setup_vertex_format()
*/
#define SWZ ((SWvertex *)0)
#define SWOffset(MEMBER) (((char *)&(SWZ->MEMBER)) - ((char *)SWZ))
#define EMIT_ATTR( ATTR, STYLE, MEMBER ) \
do { \
map[e].attrib = (ATTR); \
map[e].format = (STYLE); \
map[e].offset = SWOffset(MEMBER); \
e++; \
} while (0)
/**
* Tell the tnl module how to build SWvertex objects for swrast.
* We'll build the map[] array with that info and pass it to
* _tnl_install_attrs().
*/
static void
setup_vertex_format(struct gl_context *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
GLboolean intColors = !ctx->FragmentProgram._Current
&& !_mesa_ati_fragment_shader_enabled(ctx)
&& ctx->RenderMode == GL_RENDER
&& CHAN_TYPE != GL_FLOAT;
if (intColors != swsetup->intColors ||
tnl->render_inputs_bitset != swsetup->last_index_bitset) {
GLbitfield64 index_bitset = tnl->render_inputs_bitset;
struct tnl_attr_map map[_TNL_ATTRIB_MAX];
unsigned int i, e = 0;
swsetup->intColors = intColors;
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, attrib[VARYING_SLOT_POS] );
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR0)) {
if (swsetup->intColors)
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4CHAN_4F_RGBA, color );
else
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4F, attrib[VARYING_SLOT_COL0]);
}
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) {
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_4F, attrib[VARYING_SLOT_COL1]);
}
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) {
const GLint emit = ctx->FragmentProgram._Current ? EMIT_4F : EMIT_1F;
EMIT_ATTR( _TNL_ATTRIB_FOG, emit, attrib[VARYING_SLOT_FOGC]);
}
if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX))
{
for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) {
EMIT_ATTR( _TNL_ATTRIB_TEX(i), EMIT_4F,
attrib[VARYING_SLOT_TEX0 + i] );
}
}
}
/* shader varying vars */
if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_GENERIC0, _TNL_NUM_GENERIC)) {
for (i = 0; i < ctx->Const.MaxVarying; i++) {
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_GENERIC(i))) {
EMIT_ATTR( _TNL_ATTRIB_GENERIC(i), VARYING_EMIT_STYLE,
attrib[VARYING_SLOT_VAR0 + i] );
}
}
}
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE))
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, pointSize );
_tnl_install_attrs( ctx, map, e,
tnl->_WindowMap.m,
sizeof(SWvertex) );
swsetup->last_index_bitset = index_bitset;
}
}
/**
* Prepare to render a vertex buffer.
* Called via tnl->Driver.Render.Start.
*/
static void
_swsetup_RenderStart( struct gl_context *ctx )
{
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
if (swsetup->NewState & _SWSETUP_NEW_RENDERINDEX) {
_swsetup_choose_trifuncs(ctx);
}
if (swsetup->NewState & _NEW_PROGRAM) {
swsetup->last_index_bitset = 0;
}
swsetup->NewState = 0;
/* This will change if drawing unfilled tris */
_swrast_SetFacing(ctx, 0);
_swrast_render_start(ctx);
/* Important */
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
setup_vertex_format(ctx);
}
/*
* We patch this function into tnl->Driver.Render.Finish.
* It's called when we finish rendering a vertex buffer.
*/
static void
_swsetup_RenderFinish( struct gl_context *ctx )
{
_swrast_render_finish( ctx );
}
void
_swsetup_InvalidateState( struct gl_context *ctx, GLuint new_state )
{
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
swsetup->NewState |= new_state;
_tnl_invalidate_vertex_state( ctx, new_state );
}
void
_swsetup_Wakeup( struct gl_context *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
tnl->Driver.Render.Start = _swsetup_RenderStart;
tnl->Driver.Render.Finish = _swsetup_RenderFinish;
tnl->Driver.Render.PrimitiveNotify = _swsetup_RenderPrimitive;
tnl->Driver.Render.Interp = _tnl_interp;
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; /* new */
tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; /* new */
/* points */
/* line */
/* triangle */
/* quad */
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
tnl->Driver.Render.Multipass = 0;
_tnl_invalidate_vertices( ctx, ~0 );
_tnl_need_projected_coords( ctx, GL_TRUE );
_swsetup_InvalidateState( ctx, ~0 );
swsetup->verts = (SWvertex *)tnl->clipspace.vertex_buf;
swsetup->last_index_bitset = 0;
}
/**
* Populate a swrast SWvertex from an attrib-style vertex.
*/
void
_swsetup_Translate( struct gl_context *ctx, const void *vertex, SWvertex *dest )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
const GLfloat *m = tnl->_WindowMap.m;
GLfloat tmp[4];
GLuint i;
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_POS, tmp );
dest->attrib[VARYING_SLOT_POS][0] = m[0] * tmp[0] + m[12];
dest->attrib[VARYING_SLOT_POS][1] = m[5] * tmp[1] + m[13];
dest->attrib[VARYING_SLOT_POS][2] = m[10] * tmp[2] + m[14];
dest->attrib[VARYING_SLOT_POS][3] = tmp[3];
/** XXX try to limit these loops someday */
for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_TEX0 + i,
dest->attrib[VARYING_SLOT_TEX0 + i] );
for (i = 0 ; i < ctx->Const.MaxVarying ; i++)
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_GENERIC0 + i,
dest->attrib[VARYING_SLOT_VAR0 + i] );
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR0,
dest->attrib[VARYING_SLOT_COL0] );
UNCLAMPED_FLOAT_TO_RGBA_CHAN(dest->color, dest->attrib[VARYING_SLOT_COL0]);
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR1,
dest->attrib[VARYING_SLOT_COL1]);
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_FOG, tmp );
dest->attrib[VARYING_SLOT_FOGC][0] = tmp[0];
/* XXX See _tnl_get_attr about pointsize ... */
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_POINTSIZE, tmp );
dest->pointSize = tmp[0];
}

View File

@ -1,45 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#ifndef SS_CONTEXT_H
#define SS_CONTEXT_H
#include "main/glheader.h"
#include "swrast/swrast.h"
#include "tnl/t_context.h"
typedef struct {
GLuint NewState;
GLenum render_prim;
GLbitfield64 last_index_bitset;
SWvertex *verts;
GLboolean intColors;
} SScontext;
#define SWSETUP_CONTEXT(ctx) ((SScontext *)ctx->swsetup_context)
#endif

View File

@ -1,267 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "c99_math.h"
#include "main/glheader.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/stencil.h"
#include "main/state.h"
#include "tnl/t_context.h"
#include "ss_triangle.h"
#include "ss_context.h"
#define SS_OFFSET_BIT 0x1
#define SS_TWOSIDE_BIT 0x2
#define SS_UNFILLED_BIT 0x4
#define SS_MAX_TRIFUNC 0x8
static tnl_triangle_func tri_tab[SS_MAX_TRIFUNC];
static tnl_quad_func quad_tab[SS_MAX_TRIFUNC];
/*
* Render a triangle respecting edge flags.
*/
typedef void (* swsetup_edge_render_prim_tri)(struct gl_context *ctx,
const GLubyte *ef,
GLuint e0,
GLuint e1,
GLuint e2,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2);
/*
* Render a triangle using lines and respecting edge flags.
*/
static void
_swsetup_edge_render_line_tri(struct gl_context *ctx,
const GLubyte *ef,
GLuint e0,
GLuint e1,
GLuint e2,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
if (swsetup->render_prim == GL_POLYGON) {
if (ef[e2]) _swrast_Line( ctx, v2, v0 );
if (ef[e0]) _swrast_Line( ctx, v0, v1 );
if (ef[e1]) _swrast_Line( ctx, v1, v2 );
} else {
if (ef[e0]) _swrast_Line( ctx, v0, v1 );
if (ef[e1]) _swrast_Line( ctx, v1, v2 );
if (ef[e2]) _swrast_Line( ctx, v2, v0 );
}
}
/*
* Render a triangle using points and respecting edge flags.
*/
static void
_swsetup_edge_render_point_tri(struct gl_context *ctx,
const GLubyte *ef,
GLuint e0,
GLuint e1,
GLuint e2,
const SWvertex *v0,
const SWvertex *v1,
const SWvertex *v2)
{
if (ef[e0]) _swrast_Point( ctx, v0 );
if (ef[e1]) _swrast_Point( ctx, v1 );
if (ef[e2]) _swrast_Point( ctx, v2 );
_swrast_flush(ctx);
}
/*
* Render a triangle respecting cull and shade model.
*/
static void _swsetup_render_tri(struct gl_context *ctx,
GLuint e0,
GLuint e1,
GLuint e2,
GLuint facing,
swsetup_edge_render_prim_tri render)
{
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLubyte *ef = VB->EdgeFlag;
SWvertex *verts = swsetup->verts;
SWvertex *v0 = &verts[e0];
SWvertex *v1 = &verts[e1];
SWvertex *v2 = &verts[e2];
/* cull testing */
if (ctx->Polygon.CullFlag) {
if (facing == 1 && ctx->Polygon.CullFaceMode != GL_FRONT)
return;
if (facing == 0 && ctx->Polygon.CullFaceMode != GL_BACK)
return;
}
_swrast_SetFacing(ctx, facing);
if (ctx->Light.ShadeModel == GL_FLAT) {
GLchan c[2][4];
GLfloat s[2][4];
/* save colors/indexes for v0, v1 vertices */
COPY_CHAN4(c[0], v0->color);
COPY_CHAN4(c[1], v1->color);
COPY_4V(s[0], v0->attrib[VARYING_SLOT_COL1]);
COPY_4V(s[1], v1->attrib[VARYING_SLOT_COL1]);
/* copy v2 color/indexes to v0, v1 indexes */
COPY_CHAN4(v0->color, v2->color);
COPY_CHAN4(v1->color, v2->color);
COPY_4V(v0->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
COPY_4V(v1->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
render(ctx, ef, e0, e1, e2, v0, v1, v2);
COPY_CHAN4(v0->color, c[0]);
COPY_CHAN4(v1->color, c[1]);
COPY_4V(v0->attrib[VARYING_SLOT_COL1], s[0]);
COPY_4V(v1->attrib[VARYING_SLOT_COL1], s[1]);
}
else {
render(ctx, ef, e0, e1, e2, v0, v1, v2);
}
}
#define SS_COLOR(a,b) UNCLAMPED_FLOAT_TO_RGBA_CHAN(a,b)
#define SS_SPEC(a,b) COPY_4V(a,b)
#define SS_IND(a,b) (a = b)
#define IND (0)
#define TAG(x) x##_rgba
#include "ss_tritmp.h"
#define IND (SS_OFFSET_BIT)
#define TAG(x) x##_offset_rgba
#include "ss_tritmp.h"
#define IND (SS_TWOSIDE_BIT)
#define TAG(x) x##_twoside_rgba
#include "ss_tritmp.h"
#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT)
#define TAG(x) x##_offset_twoside_rgba
#include "ss_tritmp.h"
#define IND (SS_UNFILLED_BIT)
#define TAG(x) x##_unfilled_rgba
#include "ss_tritmp.h"
#define IND (SS_OFFSET_BIT|SS_UNFILLED_BIT)
#define TAG(x) x##_offset_unfilled_rgba
#include "ss_tritmp.h"
#define IND (SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
#define TAG(x) x##_twoside_unfilled_rgba
#include "ss_tritmp.h"
#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
#define TAG(x) x##_offset_twoside_unfilled_rgba
#include "ss_tritmp.h"
void _swsetup_trifuncs_init( struct gl_context *ctx )
{
(void) ctx;
init_rgba();
init_offset_rgba();
init_twoside_rgba();
init_offset_twoside_rgba();
init_unfilled_rgba();
init_offset_unfilled_rgba();
init_twoside_unfilled_rgba();
init_offset_twoside_unfilled_rgba();
}
static void swsetup_points( struct gl_context *ctx, GLuint first, GLuint last )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
GLuint i;
if (VB->Elts) {
for (i = first; i < last; i++)
if (VB->ClipMask[VB->Elts[i]] == 0)
_swrast_Point( ctx, &verts[VB->Elts[i]] );
}
else {
for (i = first; i < last; i++)
if (VB->ClipMask[i] == 0)
_swrast_Point( ctx, &verts[i] );
}
}
static void swsetup_line( struct gl_context *ctx, GLuint v0, GLuint v1 )
{
SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
_swrast_Line( ctx, &verts[v0], &verts[v1] );
}
void _swsetup_choose_trifuncs( struct gl_context *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint ind = 0;
if (ctx->Polygon.OffsetPoint ||
ctx->Polygon.OffsetLine ||
ctx->Polygon.OffsetFill)
ind |= SS_OFFSET_BIT;
if ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) ||
(ctx->VertexProgram._Current && ctx->VertexProgram.TwoSideEnabled))
ind |= SS_TWOSIDE_BIT;
/* We piggyback the two-sided stencil front/back determination on the
* unfilled triangle path.
*/
if (ctx->Polygon.FrontMode != GL_FILL ||
ctx->Polygon.BackMode != GL_FILL ||
(ctx->Stencil.Enabled && _mesa_stencil_is_two_sided(ctx)))
ind |= SS_UNFILLED_BIT;
tnl->Driver.Render.Triangle = tri_tab[ind];
tnl->Driver.Render.Quad = quad_tab[ind];
tnl->Driver.Render.Line = swsetup_line;
tnl->Driver.Render.Points = swsetup_points;
}

View File

@ -1,38 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#ifndef SS_TRIANGLE_H
#define SS_TRIANGLE_H
struct gl_context;
void _swsetup_trifuncs_init( struct gl_context *ctx );
void _swsetup_choose_trifuncs( struct gl_context *ctx );
#endif

View File

@ -1,248 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
/**
* This is where we handle assigning vertex colors based on front/back
* facing, compute polygon offset and handle glPolygonMode().
*/
static void TAG(triangle)(struct gl_context *ctx, GLuint e0, GLuint e1, GLuint e2 )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
SWvertex *v[3];
GLfloat z[3];
GLfloat offset, oz0, oz1, oz2;
GLenum mode = GL_FILL;
GLuint facing = 0;
GLchan saved_color[3][4] = { { 0 } };
GLfloat saved_col0[3][4] = { { 0 } };
GLfloat saved_spec[3][4] = { { 0 } };
v[0] = &verts[e0];
v[1] = &verts[e1];
v[2] = &verts[e2];
if (IND & (SS_TWOSIDE_BIT | SS_OFFSET_BIT | SS_UNFILLED_BIT))
{
GLfloat ex = v[0]->attrib[VARYING_SLOT_POS][0] - v[2]->attrib[VARYING_SLOT_POS][0];
GLfloat ey = v[0]->attrib[VARYING_SLOT_POS][1] - v[2]->attrib[VARYING_SLOT_POS][1];
GLfloat fx = v[1]->attrib[VARYING_SLOT_POS][0] - v[2]->attrib[VARYING_SLOT_POS][0];
GLfloat fy = v[1]->attrib[VARYING_SLOT_POS][1] - v[2]->attrib[VARYING_SLOT_POS][1];
GLfloat cc = ex*fy - ey*fx;
if (IND & (SS_TWOSIDE_BIT | SS_UNFILLED_BIT))
{
facing = (cc < 0.0F) ^ _mesa_polygon_get_front_bit(ctx);
if (IND & SS_UNFILLED_BIT)
mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
if (facing == 1) {
if (IND & SS_TWOSIDE_BIT) {
if (VB->BackfaceColorPtr) {
GLfloat (*vbcolor)[4] = VB->BackfaceColorPtr->data;
if (swsetup->intColors) {
COPY_CHAN4(saved_color[0], v[0]->color);
COPY_CHAN4(saved_color[1], v[1]->color);
COPY_CHAN4(saved_color[2], v[2]->color);
}
else {
COPY_4V(saved_col0[0], v[0]->attrib[VARYING_SLOT_COL0]);
COPY_4V(saved_col0[1], v[1]->attrib[VARYING_SLOT_COL0]);
COPY_4V(saved_col0[2], v[2]->attrib[VARYING_SLOT_COL0]);
}
if (VB->BackfaceColorPtr->stride) {
if (swsetup->intColors) {
SS_COLOR(v[0]->color, vbcolor[e0]);
SS_COLOR(v[1]->color, vbcolor[e1]);
SS_COLOR(v[2]->color, vbcolor[e2]);
}
else {
COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], vbcolor[e0]);
COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], vbcolor[e1]);
COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], vbcolor[e2]);
}
}
else {
/* flat shade */
if (swsetup->intColors) {
SS_COLOR(v[0]->color, vbcolor[0]);
SS_COLOR(v[1]->color, vbcolor[0]);
SS_COLOR(v[2]->color, vbcolor[0]);
}
else {
COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
}
}
}
if (VB->BackfaceSecondaryColorPtr) {
GLfloat (*vbspec)[4] = VB->BackfaceSecondaryColorPtr->data;
COPY_4V(saved_spec[0], v[0]->attrib[VARYING_SLOT_COL1]);
COPY_4V(saved_spec[1], v[1]->attrib[VARYING_SLOT_COL1]);
COPY_4V(saved_spec[2], v[2]->attrib[VARYING_SLOT_COL1]);
if (VB->BackfaceSecondaryColorPtr->stride) {
SS_SPEC(v[0]->attrib[VARYING_SLOT_COL1], vbspec[e0]);
SS_SPEC(v[1]->attrib[VARYING_SLOT_COL1], vbspec[e1]);
SS_SPEC(v[2]->attrib[VARYING_SLOT_COL1], vbspec[e2]);
}
else {
SS_SPEC(v[0]->attrib[VARYING_SLOT_COL1], vbspec[0]);
SS_SPEC(v[1]->attrib[VARYING_SLOT_COL1], vbspec[0]);
SS_SPEC(v[2]->attrib[VARYING_SLOT_COL1], vbspec[0]);
}
}
}
}
}
if (IND & SS_OFFSET_BIT) {
const GLfloat max = ctx->DrawBuffer->_DepthMaxF;
/* save original Z values (restored later) */
z[0] = v[0]->attrib[VARYING_SLOT_POS][2];
z[1] = v[1]->attrib[VARYING_SLOT_POS][2];
z[2] = v[2]->attrib[VARYING_SLOT_POS][2];
/* Note that Z values are already scaled to [0,65535] (for example)
* so no MRD value is used here.
*/
offset = ctx->Polygon.OffsetUnits;
if (cc * cc > 1e-16F) {
const GLfloat ez = z[0] - z[2];
const GLfloat fz = z[1] - z[2];
const GLfloat oneOverArea = 1.0F / cc;
const GLfloat dzdx = fabsf((ey * fz - ez * fy) * oneOverArea);
const GLfloat dzdy = fabsf((ez * fx - ex * fz) * oneOverArea);
offset += MAX2(dzdx, dzdy) * ctx->Polygon.OffsetFactor;
}
/* new Z values */
oz0 = CLAMP(v[0]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
oz1 = CLAMP(v[1]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
oz2 = CLAMP(v[2]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
}
}
if (mode == GL_POINT) {
if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetPoint) {
v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
}
_swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_point_tri);
} else if (mode == GL_LINE) {
if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetLine) {
v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
}
_swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_line_tri);
} else {
if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetFill) {
v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
}
_swrast_Triangle( ctx, v[0], v[1], v[2] );
}
/*
* Restore original vertex colors, etc.
*/
if (IND & SS_OFFSET_BIT) {
v[0]->attrib[VARYING_SLOT_POS][2] = z[0];
v[1]->attrib[VARYING_SLOT_POS][2] = z[1];
v[2]->attrib[VARYING_SLOT_POS][2] = z[2];
}
if (IND & SS_TWOSIDE_BIT) {
if (facing == 1) {
if (VB->BackfaceColorPtr) {
if (swsetup->intColors) {
COPY_CHAN4(v[0]->color, saved_color[0]);
COPY_CHAN4(v[1]->color, saved_color[1]);
COPY_CHAN4(v[2]->color, saved_color[2]);
}
else {
COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], saved_col0[0]);
COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], saved_col0[1]);
COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], saved_col0[2]);
}
}
if (VB->BackfaceSecondaryColorPtr) {
COPY_4V(v[0]->attrib[VARYING_SLOT_COL1], saved_spec[0]);
COPY_4V(v[1]->attrib[VARYING_SLOT_COL1], saved_spec[1]);
COPY_4V(v[2]->attrib[VARYING_SLOT_COL1], saved_spec[2]);
}
}
}
}
/* Need to fixup edgeflags when decomposing to triangles:
*/
static void TAG(quadfunc)( struct gl_context *ctx, GLuint v0,
GLuint v1, GLuint v2, GLuint v3 )
{
if (IND & SS_UNFILLED_BIT) {
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
if (VB->EdgeFlag) { /* XXX this test shouldn't be needed (bug 12614) */
GLubyte ef1 = VB->EdgeFlag[v1];
GLubyte ef3 = VB->EdgeFlag[v3];
VB->EdgeFlag[v1] = 0;
TAG(triangle)( ctx, v0, v1, v3 );
VB->EdgeFlag[v1] = ef1;
VB->EdgeFlag[v3] = 0;
TAG(triangle)( ctx, v1, v2, v3 );
VB->EdgeFlag[v3] = ef3;
}
} else {
TAG(triangle)( ctx, v0, v1, v3 );
TAG(triangle)( ctx, v1, v2, v3 );
}
}
static void TAG(init)( void )
{
tri_tab[IND] = TAG(triangle);
quad_tab[IND] = TAG(quadfunc);
}
#undef IND
#undef TAG

View File

@ -1,37 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#ifndef SS_VB_H
#define SS_VB_H
struct gl_context;
void _swsetup_vb_init( struct gl_context *ctx );
void _swsetup_choose_rastersetup_func( struct gl_context *ctx );
#endif

View File

@ -1,61 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
/* Public interface to the swrast_setup module. This module provides
* an implementation of the driver interface to t_vb_render.c, and uses
* the software rasterizer (swrast) to perform actual rasterization.
*
* The internals of the implementation are private, but can be hooked
* into tnl at any time (except between RenderStart/RenderEnd) by
* calling _swsetup_Wakeup().
*/
#ifndef SWRAST_SETUP_H
#define SWRAST_SETUP_H
#include "swrast/swrast.h"
extern GLboolean
_swsetup_CreateContext( struct gl_context *ctx );
extern void
_swsetup_DestroyContext( struct gl_context *ctx );
extern void
_swsetup_InvalidateState( struct gl_context *ctx, GLuint new_state );
extern void
_swsetup_Wakeup( struct gl_context *ctx );
/* Helper function to translate a hardware vertex (as understood by
* the tnl/t_vertex.c code) to a swrast vertex.
*/
extern void
_swsetup_Translate( struct gl_context *ctx, const void *vertex, SWvertex *dest );
#endif

View File

@ -1,100 +0,0 @@
INTRODUCTION
A generic, configurable software implementation of GL transformation &
lighting.
This module provides an implementation of the routines required by the
'vtxfmt' mechanism of core mesa for tnl functionality in all
combinations of compile and execute modes.
Most current drivers use the tnl module exclusively to provide this
functionality.
STATE
To create and destroy the module:
GLboolean _tnl_CreateContext( struct gl_context *ctx );
void _tnl_DestroyContext( struct gl_context *ctx );
The module is not active by default, and must be installed by calling
_tnl_Wakeup(). This function installs internal tnl functions into all
the vtxfmt dispatch hooks, thus taking over the task of transformation
and lighting entirely:
void _tnl_wakeup_exec( struct gl_context *ctx );
void _tnl_wakeup_save_exec( struct gl_context *ctx );
This module tracks state changes internally and maintains derived
values based on the current state. For this to work, the driver
ensure the following funciton is called whenever the state changes and
the swsetup module is 'awake':
void _tnl_InvalidateState( struct gl_context *ctx, GLuint new_state );
There is no explicit call to put the tnl module to sleep. Simply
install other function pointers into all the vtxfmt dispatch slots,
and (optionally) cease calling _tnl_InvalidateState().
CUSTOMIZATION
The module provides customizability through several mechanisms. The
most important is by allowing drivers to specify the pipeline through
which vertex data is passed, including its eventual transfer to
rasterization hardware (or software).
The default pipeline is specified in t_pipeline.c, and is usually a
starting point for driver pipelines. Some drivers will remove a stage
where hardware provides support for the implemented operation (for
instance fog where per-pixel hardware fog is available),
or add stages to shortcircuit latter operations (for
example taking advantage of hardware support for strips and other
higher-level primitives (for example the radeon driver).
In addition, the following functions provide further tweaks:
extern void
_tnl_need_projected_coords( struct gl_context *ctx, GLboolean flag );
- Direct the default vertex transformation stage to
produce/not produce projected clip coordinates.
extern void
_tnl_need_dlist_loopback( struct gl_context *ctx, GLboolean flag );
- Direct the display list component of the tnl module to
replay display lists as 'glVertex' type calls, rather than
passing the display list data directly into the tnl pipeline
mechanism.
This allows display lists to be replayed by the tnl module
even when the module is not strictly active.
extern void
_tnl_need_dlist_norm_lengths( struct gl_context *ctx, GLboolean flag );
- Direct the display list component to enable/disable caching
1/length values for display list normals. Doing so is
ususally helpful when lighting is performed in software, but
wasteful otherwise.
DRIVER INTERFACE
The module itself offers a minimal driver interface:
void (*RunPipeline)( struct gl_context *ctx );
Normally this is set to _tnl_RunPipeline(), however the driver can use
this hook to wrap checks or other code around this call.
In addition, the driver interface for the default render pipeline
stage is housed in the tnl context struct (this could be cleaner).
RENDER DRIVER INTERFACE
See t_context.h for the definition and explanation of this.

View File

@ -1,253 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/light.h"
#include "math/m_translate.h"
#include "math/m_xform.h"
#include "main/state.h"
#include "main/viewport.h"
#include "util/simple_list.h"
#include "util/u_memory.h"
#include "tnl.h"
#include "t_context.h"
#include "t_pipeline.h"
#include "vbo/vbo.h"
GLboolean
_tnl_CreateContext( struct gl_context *ctx )
{
TNLcontext *tnl;
GLuint i;
/* Create the TNLcontext structure
*/
ctx->swtnl_context = tnl = calloc(1, sizeof(TNLcontext));
if (!tnl) {
return GL_FALSE;
}
/* Initialize the VB.
*/
tnl->vb.Size = ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES;
/* Initialize tnl state.
*/
if (ctx->VertexProgram._MaintainTnlProgram) {
_tnl_install_pipeline( ctx, _tnl_vp_pipeline );
} else {
_tnl_install_pipeline( ctx, _tnl_default_pipeline );
}
_math_matrix_ctr(&tnl->_WindowMap);
tnl->NeedNdcCoords = GL_TRUE;
tnl->AllowVertexFog = GL_TRUE;
tnl->AllowPixelFog = GL_TRUE;
/* Set a few default values in the driver struct.
*/
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
tnl->Driver.NotifyMaterialChange = _tnl_validate_shine_tables;
tnl->nr_blocks = 0;
/* Lighting miscellaneous */
tnl->_ShineTabList = MALLOC_STRUCT( tnl_shine_tab );
make_empty_list( tnl->_ShineTabList );
/* Allocate 10 (arbitrary) shininess lookup tables */
for (i = 0 ; i < 10 ; i++) {
struct tnl_shine_tab *s = MALLOC_STRUCT( tnl_shine_tab );
s->shininess = -1;
s->refcount = 0;
insert_at_tail( tnl->_ShineTabList, s );
}
_math_init_transformation();
_math_init_translate();
/* Keep our list of tnl_vertex_array inputs */
_tnl_init_inputs(&tnl->draw_arrays);
return GL_TRUE;
}
void
_tnl_DestroyContext( struct gl_context *ctx )
{
struct tnl_shine_tab *s, *tmps;
TNLcontext *tnl = TNL_CONTEXT(ctx);
/* Free lighting shininess exponentiation table */
foreach_s( s, tmps, tnl->_ShineTabList ) {
free( s );
}
free( tnl->_ShineTabList );
_tnl_destroy_pipeline( ctx );
free(tnl);
ctx->swtnl_context = NULL;
}
void
_tnl_InvalidateState( struct gl_context *ctx, GLuint new_state )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
const struct gl_program *vp = ctx->VertexProgram._Current;
const struct gl_program *fp = ctx->FragmentProgram._Current;
GLuint i;
if (new_state & (_NEW_LIGHT_CONSTANTS | _NEW_MATERIAL))
_mesa_update_light_materials(ctx);
if (new_state & (_NEW_HINT | _NEW_PROGRAM)) {
assert(tnl->AllowVertexFog || tnl->AllowPixelFog);
tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
|| !tnl->AllowPixelFog) && !fp;
}
tnl->pipeline.new_state |= new_state;
/* Calculate tnl->render_inputs. This bitmask indicates which vertex
* attributes need to be emitted to the rasterizer.
*/
tnl->render_inputs_bitset = BITFIELD64_BIT(_TNL_ATTRIB_POS);
if (!fp || (fp->info.inputs_read & VARYING_BIT_COL0)) {
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_COLOR0);
}
if (_mesa_need_secondary_color(ctx))
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_COLOR1);
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
if (ctx->Texture._EnabledCoordUnits & (1 << i) ||
(fp && fp->info.inputs_read & VARYING_BIT_TEX(i)) ||
_mesa_ati_fragment_shader_enabled(ctx)) {
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_TEX(i));
}
}
if (ctx->Fog.Enabled
|| (fp != NULL && (fp->info.inputs_read & VARYING_BIT_FOGC) != 0)) {
/* Either fixed-function fog or a fragment program needs fog coord.
*/
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_FOG);
}
if (ctx->Polygon.FrontMode != GL_FILL ||
ctx->Polygon.BackMode != GL_FILL)
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_EDGEFLAG);
if (ctx->RenderMode == GL_FEEDBACK)
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_TEX0);
if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled)
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE);
/* check for varying vars which are written by the vertex program */
if (vp) {
GLuint i;
for (i = 0; i < MAX_VARYING; i++) {
if (vp->info.outputs_written &
BITFIELD64_BIT(VARYING_SLOT_VAR0 + i)) {
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_GENERIC(i));
}
}
}
if (new_state & (_NEW_VIEWPORT | _NEW_BUFFERS)) {
float scale[3], translate[3];
_mesa_get_viewport_xform(ctx, 0, scale, translate);
_math_matrix_viewport(&tnl->_WindowMap, scale, translate,
ctx->DrawBuffer->_DepthMaxF);
}
}
void
_tnl_wakeup( struct gl_context *ctx )
{
/* Assume we haven't been getting state updates either:
*/
_tnl_InvalidateState( ctx, ~0 );
#if 0
if (ctx->Light.ColorMaterialEnabled) {
_mesa_update_color_material( ctx,
ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
}
#endif
}
/**
* Drivers call this function to tell the TCL module whether or not
* it wants Normalized Device Coords (NDC) computed. I.e. whether
* we should "Divide-by-W". Software renders will want that.
*/
void
_tnl_need_projected_coords( struct gl_context *ctx, GLboolean mode )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->NeedNdcCoords = mode;
}
void
_tnl_allow_vertex_fog( struct gl_context *ctx, GLboolean value )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->AllowVertexFog = value;
tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
|| !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current;
}
void
_tnl_allow_pixel_fog( struct gl_context *ctx, GLboolean value )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->AllowPixelFog = value;
tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
|| !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current;
}

View File

@ -1,594 +0,0 @@
/*
* mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file t_context.h
* \brief TnL module datatypes and definitions.
* \author Keith Whitwell
*/
/**
* \mainpage The TNL-module
*
* TNL stands for "transform and lighting", i.e. this module implements
* a pipeline that receives as input a buffer of vertices and does all
* necessary transformations (rotations, clipping, vertex shader etc.)
* and passes then the output to the rasterizer.
*
* The tnl_pipeline contains the array of all stages, which should be
* applied. Each stage is a black-box, which is described by an
* tnl_pipeline_stage. The function ::_tnl_run_pipeline applies all the
* stages to the vertex_buffer TNLcontext::vb, where the vertex data
* is stored. The last stage in the pipeline is the rasterizer.
*
*/
#ifndef _T_CONTEXT_H
#define _T_CONTEXT_H
#include "main/glheader.h"
#include "main/mtypes.h"
#include "math/m_vector.h"
#include "vbo/vbo.h"
#include "tnl.h"
#define MAX_PIPELINE_STAGES 30
/*
* Note: The first attributes match the VERT_ATTRIB_* definitions
* in mtypes.h. However, the tnl module has additional attributes
* for materials, color indexes, edge flags, etc.
*/
/* Although it's nice to use these as bit indexes in a DWORD flag, we
* could manage without if necessary. Another limit currently is the
* number of bits allocated for these numbers in places like vertex
* program instruction formats and register layouts.
*/
/* The bit space exhaustion is a fact now, done by _TNL_ATTRIB_ATTRIBUTE* for
* GLSL vertex shader which cannot be aliased with conventional vertex attribs.
* Compacting _TNL_ATTRIB_MAT_* attribs would not work, they would not give
* as many free bits (11 plus already 1 free bit) as _TNL_ATTRIB_ATTRIBUTE*
* attribs want (16).
*/
enum {
_TNL_ATTRIB_POS,
_TNL_ATTRIB_NORMAL,
_TNL_ATTRIB_COLOR0,
_TNL_ATTRIB_COLOR1,
_TNL_ATTRIB_FOG,
_TNL_ATTRIB_COLOR_INDEX,
_TNL_ATTRIB_TEX0,
_TNL_ATTRIB_TEX1,
_TNL_ATTRIB_TEX2,
_TNL_ATTRIB_TEX3,
_TNL_ATTRIB_TEX4,
_TNL_ATTRIB_TEX5,
_TNL_ATTRIB_TEX6,
_TNL_ATTRIB_TEX7,
/* This is really a VARYING_SLOT, not an attrib. Need to fix
* tnl to understand the difference.
*/
_TNL_ATTRIB_POINTSIZE,
_TNL_ATTRIB_GENERIC0, /* doesn't really exist! */
_TNL_ATTRIB_GENERIC1,
_TNL_ATTRIB_GENERIC2,
_TNL_ATTRIB_GENERIC3,
_TNL_ATTRIB_GENERIC4,
_TNL_ATTRIB_GENERIC5,
_TNL_ATTRIB_GENERIC6,
_TNL_ATTRIB_GENERIC7,
_TNL_ATTRIB_GENERIC8,
_TNL_ATTRIB_GENERIC9,
_TNL_ATTRIB_GENERIC10,
_TNL_ATTRIB_GENERIC11,
_TNL_ATTRIB_GENERIC12,
_TNL_ATTRIB_GENERIC13,
_TNL_ATTRIB_GENERIC14,
_TNL_ATTRIB_GENERIC15,
_TNL_ATTRIB_EDGEFLAG,
_TNL_ATTRIB_MAX,
/* These alias with the generics, but they are not active
* concurrently, so it's not a problem. The TNL module
* doesn't have to do anything about this as this is how they
* are passed into the _draw_prims callback.
*
* When we generate fixed-function replacement programs (in
* t_vp_build.c currently), they refer to the appropriate
* generic attribute in order to pick up per-vertex material
* data.
*/
_TNL_ATTRIB_MAT_FRONT_AMBIENT=VERT_ATTRIB_MAT(MAT_ATTRIB_FRONT_AMBIENT),
_TNL_ATTRIB_MAT_BACK_AMBIENT,
_TNL_ATTRIB_MAT_FRONT_DIFFUSE,
_TNL_ATTRIB_MAT_BACK_DIFFUSE,
_TNL_ATTRIB_MAT_FRONT_SPECULAR,
_TNL_ATTRIB_MAT_BACK_SPECULAR,
_TNL_ATTRIB_MAT_FRONT_EMISSION,
_TNL_ATTRIB_MAT_BACK_EMISSION,
_TNL_ATTRIB_MAT_FRONT_SHININESS,
_TNL_ATTRIB_MAT_BACK_SHININESS,
_TNL_ATTRIB_MAT_FRONT_INDEXES,
_TNL_ATTRIB_MAT_BACK_INDEXES,
};
#define _TNL_ATTRIB_TEX(u) (_TNL_ATTRIB_TEX0 + (u))
#define _TNL_ATTRIB_GENERIC(n) (_TNL_ATTRIB_GENERIC0 + (n))
/* special index used for handing invalid glVertexAttribute() indices */
#define _TNL_ATTRIB_ERROR (_TNL_ATTRIB_GENERIC15 + 1)
/**
* Handy attribute ranges:
*/
#define _TNL_FIRST_PROG _TNL_ATTRIB_NORMAL
#define _TNL_LAST_PROG _TNL_ATTRIB_TEX7
#define _TNL_FIRST_TEX _TNL_ATTRIB_TEX0
#define _TNL_LAST_TEX _TNL_ATTRIB_TEX7
#define _TNL_FIRST_GENERIC _TNL_ATTRIB_GENERIC0
#define _TNL_LAST_GENERIC _TNL_ATTRIB_GENERIC15
#define _TNL_FIRST_MAT _TNL_ATTRIB_MAT_FRONT_AMBIENT /* GENERIC4 */
#define _TNL_LAST_MAT _TNL_ATTRIB_MAT_BACK_INDEXES /* GENERIC15 */
/* Number of available texture attributes */
#define _TNL_NUM_TEX 8
/* Number of available generic attributes */
#define _TNL_NUM_GENERIC 16
/* Number of attributes used for evaluators */
#define _TNL_NUM_EVAL 16
#define PRIM_BEGIN 0x10
#define PRIM_END 0x20
#define PRIM_MODE_MASK 0x0f
static inline GLuint _tnl_translate_prim( const struct _mesa_prim *prim )
{
GLuint flag;
flag = prim->mode;
if (prim->begin) flag |= PRIM_BEGIN;
if (prim->end) flag |= PRIM_END;
return flag;
}
/**
* Contains the current state of a running pipeline.
*/
struct vertex_buffer
{
GLuint Size; /**< Max vertices per vertex buffer, constant */
/* Constant over the pipeline.
*/
GLuint Count; /**< Number of vertices currently in buffer */
/* Pointers to current data. Most of the data is in AttribPtr -- all of
* it that is one of VERT_ATTRIB_X. For things only produced by TNL,
* such as backface color or eye-space coordinates, they are stored
* here.
*/
GLuint *Elts;
GLvector4f *EyePtr; /* _TNL_BIT_POS */
GLvector4f *ClipPtr; /* _TNL_BIT_POS */
GLvector4f *NdcPtr; /* _TNL_BIT_POS */
GLubyte ClipOrMask; /* _TNL_BIT_POS */
GLubyte ClipAndMask; /* _TNL_BIT_POS */
GLubyte *ClipMask; /* _TNL_BIT_POS */
GLfloat *NormalLengthPtr; /* _TNL_BIT_NORMAL */
GLboolean *EdgeFlag; /* _TNL_BIT_EDGEFLAG */
GLvector4f *BackfaceIndexPtr;
GLvector4f *BackfaceColorPtr;
GLvector4f *BackfaceSecondaryColorPtr;
const struct _mesa_prim *Primitive;
GLuint PrimitiveCount;
/* Inputs to the vertex program stage */
GLvector4f *AttribPtr[_TNL_ATTRIB_MAX];
};
/**
* Describes an individual operation on the pipeline.
*/
struct tnl_pipeline_stage
{
const char *name;
/* Private data for the pipeline stage:
*/
void *privatePtr;
/* Allocate private data
*/
GLboolean (*create)( struct gl_context *ctx, struct tnl_pipeline_stage * );
/* Free private data.
*/
void (*destroy)( struct tnl_pipeline_stage * );
/* Called on any statechange or input array size change or
* input array change to/from zero stride.
*/
void (*validate)( struct gl_context *ctx, struct tnl_pipeline_stage * );
/* Called from _tnl_run_pipeline(). The stage.changed_inputs value
* encodes all inputs to thee struct which have changed. If
* non-zero, recompute all affected outputs of the stage, otherwise
* execute any 'sideeffects' of the stage.
*
* Return value: GL_TRUE - keep going
* GL_FALSE - finished pipeline
*/
GLboolean (*run)( struct gl_context *ctx, struct tnl_pipeline_stage * );
};
/** Contains the array of all pipeline stages.
* The default values are defined at the end of t_pipeline.c
*/
struct tnl_pipeline {
GLuint last_attrib_stride[_TNL_ATTRIB_MAX];
GLuint last_attrib_size[_TNL_ATTRIB_MAX];
GLuint input_changes;
GLuint new_state;
struct tnl_pipeline_stage stages[MAX_PIPELINE_STAGES+1];
GLuint nr_stages;
};
struct tnl_clipspace;
struct tnl_clipspace_attr;
typedef void (*tnl_extract_func)( const struct tnl_clipspace_attr *a,
GLfloat *out,
const GLubyte *v );
typedef void (*tnl_insert_func)( const struct tnl_clipspace_attr *a,
GLubyte *v,
const GLfloat *in );
typedef void (*tnl_emit_func)( struct gl_context *ctx,
GLuint count,
GLubyte *dest );
/**
* Describes how to convert/move a vertex attribute from a vertex array
* to a vertex structure.
*/
struct tnl_clipspace_attr
{
GLuint attrib; /* which vertex attrib (0=position, etc) */
GLuint format;
GLuint vertoffset; /* position of the attrib in the vertex struct */
GLuint vertattrsize; /* size of the attribute in bytes */
GLubyte *inputptr;
GLuint inputstride;
GLuint inputsize;
const tnl_insert_func *insert;
tnl_insert_func emit;
tnl_extract_func extract;
const GLfloat *vp; /* NDC->Viewport mapping matrix */
};
typedef void (*tnl_points_func)( struct gl_context *ctx, GLuint first, GLuint last );
typedef void (*tnl_line_func)( struct gl_context *ctx, GLuint v1, GLuint v2 );
typedef void (*tnl_triangle_func)( struct gl_context *ctx,
GLuint v1, GLuint v2, GLuint v3 );
typedef void (*tnl_quad_func)( struct gl_context *ctx, GLuint v1, GLuint v2,
GLuint v3, GLuint v4 );
typedef void (*tnl_render_func)( struct gl_context *ctx, GLuint start, GLuint count,
GLuint flags );
typedef void (*tnl_interp_func)( struct gl_context *ctx,
GLfloat t, GLuint dst, GLuint out, GLuint in,
GLboolean force_boundary );
typedef void (*tnl_copy_pv_func)( struct gl_context *ctx, GLuint dst, GLuint src );
typedef void (*tnl_setup_func)( struct gl_context *ctx,
GLuint start, GLuint end,
GLuint new_inputs);
struct tnl_attr_type {
GLuint format;
GLuint size;
GLuint stride;
GLuint offset;
};
struct tnl_clipspace_fastpath {
GLuint vertex_size;
GLuint attr_count;
GLboolean match_strides;
struct tnl_attr_type *attr;
tnl_emit_func func;
struct tnl_clipspace_fastpath *next;
};
/**
* Used to describe conversion of vertex arrays to vertex structures.
* I.e. Structure of arrays to arrays of structs.
*/
struct tnl_clipspace
{
GLboolean need_extras;
GLuint new_inputs;
GLubyte *vertex_buf;
GLuint vertex_size;
GLuint max_vertex_size;
struct tnl_clipspace_attr attr[_TNL_ATTRIB_MAX];
GLuint attr_count;
tnl_emit_func emit;
tnl_interp_func interp;
tnl_copy_pv_func copy_pv;
/* Parameters and constants for codegen:
*/
GLboolean need_viewport;
GLfloat vp_scale[4];
GLfloat vp_xlate[4];
GLfloat chan_scale[4];
GLfloat identity[4];
struct tnl_clipspace_fastpath *fastpath;
void (*codegen_emit)( struct gl_context *ctx );
};
#define SHINE_TABLE_SIZE 256 /**< Material shininess lookup table sizes */
/**
* Material shininess lookup table.
*/
struct tnl_shine_tab
{
struct tnl_shine_tab *next, *prev;
GLfloat tab[SHINE_TABLE_SIZE+1];
GLfloat shininess;
GLuint refcount;
};
struct tnl_device_driver
{
/***
*** TNL Pipeline
***/
void (*RunPipeline)(struct gl_context *ctx);
/* Replaces PipelineStart/PipelineFinish -- intended to allow
* drivers to wrap _tnl_run_pipeline() with code to validate state
* and grab/release hardware locks.
*/
void (*NotifyMaterialChange)(struct gl_context *ctx);
/* Alert tnl-aware drivers of changes to material.
*/
/***
*** Rendering -- These functions called only from t_vb_render.c
***/
struct
{
void (*Start)(struct gl_context *ctx);
void (*Finish)(struct gl_context *ctx);
/* Called before and after all rendering operations, including DrawPixels,
* ReadPixels, Bitmap, span functions, and CopyTexImage, etc commands.
* These are a suitable place for grabbing/releasing hardware locks.
*/
void (*PrimitiveNotify)(struct gl_context *ctx, GLenum mode);
/* Called between RenderStart() and RenderFinish() to indicate the
* type of primitive we're about to draw. Mode will be one of the
* modes accepted by glBegin().
*/
tnl_interp_func Interp;
/* The interp function is called by the clipping routines when we need
* to generate an interpolated vertex. All pertinant vertex ancilliary
* data should be computed by interpolating between the 'in' and 'out'
* vertices.
*/
tnl_copy_pv_func CopyPV;
/* The copy function is used to make a copy of a vertex. All pertinant
* vertex attributes should be copied.
*/
void (*ClippedPolygon)( struct gl_context *ctx, const GLuint *elts, GLuint n );
/* Render a polygon with <n> vertices whose indexes are in the <elts>
* array.
*/
void (*ClippedLine)( struct gl_context *ctx, GLuint v0, GLuint v1 );
/* Render a line between the two vertices given by indexes v0 and v1. */
tnl_points_func Points; /* must now respect vb->elts */
tnl_line_func Line;
tnl_triangle_func Triangle;
tnl_quad_func Quad;
/* These functions are called in order to render points, lines,
* triangles and quads. These are only called via the T&L module.
*/
tnl_render_func *PrimTabVerts;
tnl_render_func *PrimTabElts;
/* Render whole unclipped primitives (points, lines, linestrips,
* lineloops, etc). The tables are indexed by the GL enum of the
* primitive to be rendered. RenderTabVerts is used for non-indexed
* arrays of vertices. RenderTabElts is used for indexed arrays of
* vertices.
*/
void (*ResetLineStipple)( struct gl_context *ctx );
/* Reset the hardware's line stipple counter.
*/
tnl_setup_func BuildVertices;
/* This function is called whenever new vertices are required for
* rendering. The vertices in question are those n such that start
* <= n < end. The new_inputs parameter indicates those fields of
* the vertex which need to be updated, if only a partial repair of
* the vertex is required.
*
* This function is called only from _tnl_render_stage in tnl/t_render.c.
*/
GLboolean (*Multipass)( struct gl_context *ctx, GLuint passno );
/* Driver may request additional render passes by returning GL_TRUE
* when this function is called. This function will be called
* after the first pass, and passes will be made until the function
* returns GL_FALSE. If no function is registered, only one pass
* is made.
*
* This function will be first invoked with passno == 1.
*/
} Render;
};
/**
* Utility that tracks and updates the current array entries.
*/
struct tnl_inputs
{
/**
* Array of inputs to be set to the _DrawArrays pointer.
* The array contains pointers into the _DrawVAO and to the vbo modules
* current values. The array of pointers is updated incrementally
* based on the current and vertex_processing_mode values below.
*/
struct tnl_vertex_array inputs[VERT_ATTRIB_MAX];
/** Those VERT_BIT_'s where the inputs array point to current values. */
GLbitfield current;
/** Store which aliasing current values - generics or materials - are set. */
gl_vertex_processing_mode vertex_processing_mode;
};
/**
* Initialize inputs.
*/
void
_tnl_init_inputs(struct tnl_inputs *inputs);
/**
* Update the tnl_vertex_array array inside the tnl_inputs structure
* provided the current _VPMode, the provided vao and
* the vao's enabled arrays filtered by the filter bitmask.
*/
void
_tnl_update_inputs(struct gl_context *ctx, struct tnl_inputs *inputs);
/**
* Context state for T&L context.
*/
typedef struct
{
/* Driver interface.
*/
struct tnl_device_driver Driver;
/* Pipeline
*/
struct tnl_pipeline pipeline;
struct vertex_buffer vb;
/* Clipspace/ndc/window vertex managment:
*/
struct tnl_clipspace clipspace;
GLmatrix _WindowMap;
/* Probably need a better configuration mechanism:
*/
GLboolean NeedNdcCoords;
GLboolean AllowVertexFog;
GLboolean AllowPixelFog;
GLboolean _DoVertexFog; /* eval fog function at each vertex? */
GLbitfield64 render_inputs_bitset;
GLvector4f tmp_inputs[VERT_ATTRIB_MAX];
/* Temp storage for t_draw.c:
*/
GLubyte *block[VERT_ATTRIB_MAX];
GLuint nr_blocks;
GLuint CurInstance;
struct tnl_shine_tab *_ShineTable[2]; /**< Active shine tables */
struct tnl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */
/**@}*/
/* The list of tnl_vertex_array inputs. */
struct tnl_inputs draw_arrays;
} TNLcontext;
#define TNL_CONTEXT(ctx) ((TNLcontext *)((ctx)->swtnl_context))
#define TYPE_IDX(t) ((t) & 0xf)
#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */
extern void
tnl_clip_prepare(struct gl_context *ctx);
#endif

View File

@ -1,657 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include <stdio.h>
#include "main/glheader.h"
#include "main/arrayobj.h"
#include "main/bufferobj.h"
#include "main/condrender.h"
#include "main/context.h"
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/enums.h"
#include "main/varray.h"
#include "util/half_float.h"
#include "t_context.h"
#include "t_rebase.h"
#include "tnl.h"
static GLubyte *get_space(struct gl_context *ctx, GLuint bytes)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLubyte *space = malloc(bytes);
tnl->block[tnl->nr_blocks++] = space;
return space;
}
static void free_space(struct gl_context *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
for (GLuint i = 0; i < tnl->nr_blocks; i++)
free(tnl->block[i]);
tnl->nr_blocks = 0;
}
/* Convert the incoming array to GLfloats. Understands the
* array->Normalized flag and selects the correct conversion method.
*/
#define CONVERT( TYPE, MACRO ) do { \
GLuint i, j; \
if (attrib->Format.Normalized) { \
for (i = 0; i < count; i++) { \
const TYPE *in = (TYPE *)ptr; \
for (j = 0; j < sz; j++) { \
*fptr++ = MACRO(*in); \
in++; \
} \
ptr += binding->Stride; \
} \
} else { \
for (i = 0; i < count; i++) { \
const TYPE *in = (TYPE *)ptr; \
for (j = 0; j < sz; j++) { \
*fptr++ = (GLfloat)(*in); \
in++; \
} \
ptr += binding->Stride; \
} \
} \
} while (0)
/**
* Convert array of BGRA/GLubyte[4] values to RGBA/float[4]
* \param ptr input/ubyte array
* \param fptr output/float array
*/
static void
convert_bgra_to_float(const struct gl_vertex_buffer_binding *binding,
const struct gl_array_attributes *attrib,
const GLubyte *ptr, GLfloat *fptr,
GLuint count)
{
GLuint i;
assert(attrib->Format.Normalized);
assert(attrib->Format.Size == 4);
for (i = 0; i < count; i++) {
const GLubyte *in = (GLubyte *) ptr; /* in is in BGRA order */
*fptr++ = UBYTE_TO_FLOAT(in[2]); /* red */
*fptr++ = UBYTE_TO_FLOAT(in[1]); /* green */
*fptr++ = UBYTE_TO_FLOAT(in[0]); /* blue */
*fptr++ = UBYTE_TO_FLOAT(in[3]); /* alpha */
ptr += binding->Stride;
}
}
static void
convert_half_to_float(const struct gl_vertex_buffer_binding *binding,
const GLubyte *ptr, GLfloat *fptr,
GLuint count, GLuint sz)
{
GLuint i, j;
for (i = 0; i < count; i++) {
GLhalfARB *in = (GLhalfARB *)ptr;
for (j = 0; j < sz; j++)
*fptr++ = _mesa_half_to_float(in[j]);
ptr += binding->Stride;
}
}
/**
* \brief Convert fixed-point to floating-point.
*
* In OpenGL, a fixed-point number is a "signed 2's complement 16.16 scaled
* integer" (Table 2.2 of the OpenGL ES 2.0 spec).
*
* If the buffer has the \c normalized flag set, the formula
* \code normalize(x) := (2*x + 1) / (2^16 - 1) \endcode
* is used to map the fixed-point numbers into the range [-1, 1].
*/
static void
convert_fixed_to_float(const struct gl_vertex_buffer_binding *binding,
const struct gl_array_attributes *attrib,
const GLubyte *ptr, GLfloat *fptr,
GLuint count)
{
GLuint i;
GLint j;
const GLint size = attrib->Format.Size;
if (attrib->Format.Normalized) {
for (i = 0; i < count; ++i) {
const GLfixed *in = (GLfixed *) ptr;
for (j = 0; j < size; ++j) {
*fptr++ = (GLfloat) (2 * in[j] + 1) / (GLfloat) ((1 << 16) - 1);
}
ptr += binding->Stride;
}
} else {
for (i = 0; i < count; ++i) {
const GLfixed *in = (GLfixed *) ptr;
for (j = 0; j < size; ++j) {
*fptr++ = in[j] / (GLfloat) (1 << 16);
}
ptr += binding->Stride;
}
}
}
/* Adjust pointer to point at first requested element, convert to
* floating point, populate VB->AttribPtr[].
*/
static void _tnl_import_array(struct gl_context *ctx,
GLuint attr,
GLuint count,
const struct gl_vertex_buffer_binding *binding,
const struct gl_array_attributes *attrib,
const GLubyte *ptr)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint stride = binding->Stride;
if (attrib->Format.Type != GL_FLOAT) {
const GLuint sz = attrib->Format.Size;
GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
GLfloat *fptr = (GLfloat *)buf;
switch (attrib->Format.Type) {
case GL_BYTE:
CONVERT(GLbyte, BYTE_TO_FLOAT);
break;
case GL_UNSIGNED_BYTE:
if (attrib->Format.Format == GL_BGRA) {
/* See GL_EXT_vertex_array_bgra */
convert_bgra_to_float(binding, attrib, ptr, fptr, count);
}
else {
CONVERT(GLubyte, UBYTE_TO_FLOAT);
}
break;
case GL_SHORT:
CONVERT(GLshort, SHORT_TO_FLOAT);
break;
case GL_UNSIGNED_SHORT:
CONVERT(GLushort, USHORT_TO_FLOAT);
break;
case GL_INT:
CONVERT(GLint, INT_TO_FLOAT);
break;
case GL_UNSIGNED_INT:
CONVERT(GLuint, UINT_TO_FLOAT);
break;
case GL_DOUBLE:
CONVERT(GLdouble, (GLfloat));
break;
case GL_HALF_FLOAT:
convert_half_to_float(binding, ptr, fptr, count, sz);
break;
case GL_FIXED:
convert_fixed_to_float(binding, attrib, ptr, fptr, count);
break;
default:
unreachable("Invalid type.");
}
ptr = buf;
stride = sz * sizeof(GLfloat);
}
VB->AttribPtr[attr] = &tnl->tmp_inputs[attr];
VB->AttribPtr[attr]->data = (GLfloat (*)[4])ptr;
VB->AttribPtr[attr]->start = (GLfloat *)ptr;
VB->AttribPtr[attr]->count = count;
VB->AttribPtr[attr]->stride = stride;
VB->AttribPtr[attr]->size = attrib->Format.Size;
/* This should die, but so should the whole GLvector4f concept:
*/
VB->AttribPtr[attr]->flags = (((1<<attrib->Format.Size)-1) |
VEC_NOT_WRITEABLE |
(stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE));
VB->AttribPtr[attr]->storage = NULL;
}
#define CLIPVERTS ((6 + MAX_CLIP_PLANES) * 2)
static GLboolean *_tnl_import_edgeflag(struct gl_context *ctx,
const GLvector4f *input,
GLuint count)
{
const GLubyte *ptr = (const GLubyte *)input->data;
const GLuint stride = input->stride;
GLboolean *space = (GLboolean *)get_space(ctx, count + CLIPVERTS);
GLboolean *bptr = space;
for (GLuint i = 0; i < count; i++) {
*bptr++ = ((GLfloat *)ptr)[0] == 1.0F;
ptr += stride;
}
return space;
}
static void bind_inputs(struct gl_context *ctx,
const struct tnl_vertex_array *inputs,
GLint count,
struct gl_buffer_object **bo,
GLuint *nr_bo)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
/* Map all the VBOs
*/
for (unsigned i = 0; i < VERT_ATTRIB_MAX; i++) {
const struct tnl_vertex_array *array = &inputs[i];
const struct gl_vertex_buffer_binding *binding = array->BufferBinding;
const struct gl_array_attributes *attrib = array->VertexAttrib;
const void *ptr;
if (binding->BufferObj) {
if (!binding->BufferObj->Mappings[MAP_INTERNAL].Pointer) {
bo[*nr_bo] = binding->BufferObj;
(*nr_bo)++;
ctx->Driver.MapBufferRange(ctx, 0, binding->BufferObj->Size,
GL_MAP_READ_BIT,
binding->BufferObj,
MAP_INTERNAL);
assert(binding->BufferObj->Mappings[MAP_INTERNAL].Pointer);
}
ptr = ADD_POINTERS(binding->BufferObj->Mappings[MAP_INTERNAL].Pointer,
binding->Offset + attrib->RelativeOffset);
} else
ptr = attrib->Ptr;
/* Just make sure the array is floating point, otherwise convert to
* temporary storage.
*
* XXX: remove the GLvector4f type at some stage and just use
* client arrays.
*/
_tnl_import_array(ctx, i, count, binding, attrib, ptr);
}
/* We process only the vertices between min & max index:
*/
VB->Count = count;
/* These should perhaps be part of _TNL_ATTRIB_* */
VB->BackfaceColorPtr = NULL;
VB->BackfaceIndexPtr = NULL;
VB->BackfaceSecondaryColorPtr = NULL;
/* Clipping and drawing code still requires this to be a packed
* array of ubytes which can be written into. TODO: Fix and
* remove.
*/
if (ctx->Polygon.FrontMode != GL_FILL ||
ctx->Polygon.BackMode != GL_FILL) {
VB->EdgeFlag = _tnl_import_edgeflag(ctx,
VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG],
VB->Count);
} else {
/* the data previously pointed to by EdgeFlag may have been freed */
VB->EdgeFlag = NULL;
}
}
/* Translate indices to GLuints and store in VB->Elts.
*/
static void bind_indices(struct gl_context *ctx,
unsigned start,
const struct _mesa_index_buffer *ib,
struct gl_buffer_object **bo,
GLuint *nr_bo)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i;
const void *ptr;
if (!ib) {
VB->Elts = NULL;
return;
}
if (ib->obj) {
if (!_mesa_bufferobj_mapped(ib->obj, MAP_INTERNAL)) {
/* if the buffer object isn't mapped yet, map it now */
bo[*nr_bo] = ib->obj;
(*nr_bo)++;
ptr = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) ib->ptr,
ib->count << ib->index_size_shift,
GL_MAP_READ_BIT, ib->obj,
MAP_INTERNAL);
assert(ib->obj->Mappings[MAP_INTERNAL].Pointer);
} else {
/* user-space elements, or buffer already mapped */
ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr);
}
} else
ptr = ib->ptr;
if (ib->index_size_shift == 2 && VB->Primitive[0].basevertex == 0) {
VB->Elts = (GLuint *) ptr;
}
else {
GLuint *elts = (GLuint *)get_space(ctx, (start + ib->count) * sizeof(GLuint));
VB->Elts = elts;
elts += start;
if (ib->index_size_shift == 2) {
const GLuint *in = (GLuint *)ptr + start;
for (i = 0; i < ib->count; i++)
*elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
}
else if (ib->index_size_shift == 1) {
const GLushort *in = (GLushort *)ptr + start;
for (i = 0; i < ib->count; i++)
*elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
}
else {
const GLubyte *in = (GLubyte *)ptr + start;
for (i = 0; i < ib->count; i++)
*elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
}
}
}
static void bind_prims(struct gl_context *ctx,
const struct _mesa_prim *prim,
GLuint nr_prims)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
VB->Primitive = prim;
VB->PrimitiveCount = nr_prims;
}
static void unmap_vbos(struct gl_context *ctx,
struct gl_buffer_object **bo,
GLuint nr_bo)
{
for (GLuint i = 0; i < nr_bo; i++) {
ctx->Driver.UnmapBuffer(ctx, bo[i], MAP_INTERNAL);
}
}
/* This is the main workhorse doing all the rendering work.
*/
void _tnl_draw_prims(struct gl_context *ctx,
const struct tnl_vertex_array *arrays,
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index,
GLuint num_instances,
GLuint base_instance)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
const GLuint TEST_SPLIT = 0;
const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
GLint max_basevertex = prim->basevertex;
GLuint i;
if (!index_bounds_valid)
vbo_get_minmax_indices(ctx, prim, ib, &min_index, &max_index, nr_prims,
false, 0);
/* Mesa core state should have been validated already */
assert(ctx->NewState == 0x0);
if (!_mesa_check_conditional_render(ctx))
return; /* don't draw */
for (i = 1; i < nr_prims; i++)
max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
if (0) {
printf("%s %d..%d\n", __func__, min_index, max_index);
for (i = 0; i < nr_prims; i++)
printf("prim %d: %s start %d count %d\n", i,
_mesa_enum_to_string(prim[i].mode),
prim[i].start,
prim[i].count);
}
if (min_index) {
/* We always translate away calls with min_index != 0.
*/
t_rebase_prims(ctx, arrays, prim, nr_prims, ib,
min_index, max_index, num_instances, base_instance,
_tnl_draw_prims);
return;
}
else if ((GLint)max_index + max_basevertex > max) {
/* The software TNL pipeline has a fixed amount of storage for
* vertices and it is necessary to split incoming drawing commands
* if they exceed that limit.
*/
struct split_limits limits;
limits.max_verts = max;
limits.max_vb_size = ~0;
limits.max_indices = ~0;
/* This will split the buffers one way or another and
* recursively call back into this function.
*/
_tnl_split_prims(ctx, arrays, prim, nr_prims, ib,
0, max_index + prim->basevertex,
num_instances, base_instance,
_tnl_draw_prims,
&limits);
}
else {
/* May need to map a vertex buffer object for every attribute plus
* one for the index buffer.
*/
struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
GLuint nr_bo;
GLuint inst;
assert(num_instances > 0);
for (i = 0; i < nr_prims;) {
GLuint this_nr_prims;
/* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
* will rebase the elements to the basevertex, and we'll only
* emit strings of prims with the same basevertex in one draw call.
*/
for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
this_nr_prims++) {
if (prim[i].basevertex != prim[i + this_nr_prims].basevertex ||
prim[i].start != prim[i + this_nr_prims].start)
break;
}
/* Binding inputs may imply mapping some vertex buffer objects.
* They will need to be unmapped below.
*/
for (inst = 0; inst < num_instances; inst++) {
nr_bo = 0;
bind_prims(ctx, &prim[i], this_nr_prims);
bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1,
bo, &nr_bo);
bind_indices(ctx, prim[i].start, ib, bo, &nr_bo);
tnl->CurInstance = inst;
TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
unmap_vbos(ctx, bo, nr_bo);
free_space(ctx);
}
i += this_nr_prims;
}
}
}
void
_tnl_init_inputs(struct tnl_inputs *inputs)
{
inputs->current = 0;
inputs->vertex_processing_mode = VP_MODE_FF;
}
/**
* Update the tnl_inputs's arrays to point to the vao->_VertexArray arrays
* according to the 'enable' bitmask.
* \param enable bitfield of VERT_BIT_x flags.
*/
static inline void
update_vao_inputs(struct gl_context *ctx,
struct tnl_inputs *inputs, GLbitfield enable)
{
const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;
/* Make sure we process only arrays enabled in the VAO */
assert((enable & ~vao->_EnabledWithMapMode) == 0);
/* Fill in the client arrays from the VAO */
const struct gl_vertex_buffer_binding *bindings = &vao->BufferBinding[0];
while (enable) {
const int attr = u_bit_scan(&enable);
struct tnl_vertex_array *input = &inputs->inputs[attr];
const struct gl_array_attributes *attrib;
attrib = _mesa_draw_array_attrib(vao, attr);
input->VertexAttrib = attrib;
input->BufferBinding = &bindings[attrib->BufferBindingIndex];
}
}
/**
* Update the tnl_inputs's arrays to point to the vbo->currval arrays
* according to the 'current' bitmask.
* \param current bitfield of VERT_BIT_x flags.
*/
static inline void
update_current_inputs(struct gl_context *ctx,
struct tnl_inputs *inputs, GLbitfield current)
{
gl_vertex_processing_mode mode = ctx->VertexProgram._VPMode;
/* All previously non current array pointers need update. */
GLbitfield mask = current & ~inputs->current;
/* On mode change, the slots aliasing with materials need update too */
if (mode != inputs->vertex_processing_mode)
mask |= current & VERT_BIT_MAT_ALL;
while (mask) {
const int attr = u_bit_scan(&mask);
struct tnl_vertex_array *input = &inputs->inputs[attr];
input->VertexAttrib = _vbo_current_attrib(ctx, attr);
input->BufferBinding = _vbo_current_binding(ctx);
}
inputs->current = current;
inputs->vertex_processing_mode = mode;
}
/**
* Update the tnl_inputs's arrays to point to the vao->_VertexArray and
* vbo->currval arrays according to Array._DrawVAO and
* Array._DrawVAOEnableAttribs.
*/
void
_tnl_update_inputs(struct gl_context *ctx, struct tnl_inputs *inputs)
{
const GLbitfield enable = ctx->Array._DrawVAOEnabledAttribs;
/* Update array input pointers */
update_vao_inputs(ctx, inputs, enable);
/* The rest must be current inputs. */
update_current_inputs(ctx, inputs, ~enable & VERT_BIT_ALL);
}
const struct tnl_vertex_array *
_tnl_bind_inputs(struct gl_context *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
_tnl_update_inputs(ctx, &tnl->draw_arrays);
return tnl->draw_arrays.inputs;
}
/* This is the main entrypoint into the slimmed-down software tnl
* module. In a regular swtnl driver, this can be plugged straight
* into the ctx->Driver.Draw() callback.
*/
void
_tnl_draw(struct gl_context *ctx,
const struct _mesa_prim *prim, unsigned nr_prims,
const struct _mesa_index_buffer *ib,
bool index_bounds_valid, bool primitive_restart,
unsigned restart_index, unsigned min_index, unsigned max_index,
unsigned num_instances, unsigned base_instance)
{
/* Update TNLcontext::draw_arrays and return that pointer.
*/
const struct tnl_vertex_array* arrays = _tnl_bind_inputs(ctx);
_tnl_draw_prims(ctx, arrays, prim, nr_prims, ib,
index_bounds_valid, min_index, max_index,
num_instances, base_instance);
}
void
_tnl_init_driver_draw_function(struct dd_function_table *functions)
{
functions->Draw = _tnl_draw;
}

View File

@ -1,300 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "main/glheader.h"
#include "main/context.h"
#include "main/mtypes.h"
#include "t_context.h"
#include "t_pipeline.h"
#include "t_vp_build.h"
#include "t_vertex.h"
void _tnl_install_pipeline( struct gl_context *ctx,
const struct tnl_pipeline_stage **stages )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint i;
tnl->pipeline.new_state = ~0;
/* Create a writeable copy of each stage.
*/
for (i = 0 ; i < MAX_PIPELINE_STAGES && stages[i] ; i++) {
struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
memcpy(s, stages[i], sizeof(*s));
if (s->create)
s->create(ctx, s);
}
tnl->pipeline.nr_stages = i;
}
void _tnl_destroy_pipeline( struct gl_context *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint i;
for (i = 0 ; i < tnl->pipeline.nr_stages ; i++) {
struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
if (s->destroy)
s->destroy(s);
}
tnl->pipeline.nr_stages = 0;
}
static GLuint check_input_changes( struct gl_context *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint i;
for (i = 0; i <= _TNL_LAST_MAT; i++) {
if (tnl->vb.AttribPtr[i]->size != tnl->pipeline.last_attrib_size[i] ||
tnl->vb.AttribPtr[i]->stride != tnl->pipeline.last_attrib_stride[i]) {
tnl->pipeline.last_attrib_size[i] = tnl->vb.AttribPtr[i]->size;
tnl->pipeline.last_attrib_stride[i] = tnl->vb.AttribPtr[i]->stride;
tnl->pipeline.input_changes |= 1<<i;
}
}
return tnl->pipeline.input_changes;
}
static GLuint check_output_changes( struct gl_context *ctx )
{
#if 0
TNLcontext *tnl = TNL_CONTEXT(ctx);
for (i = 0; i < VARYING_SLOT_MAX; i++) {
if (tnl->vb.ResultPtr[i]->size != tnl->last_result_size[i] ||
tnl->vb.ResultPtr[i]->stride != tnl->last_result_stride[i]) {
tnl->last_result_size[i] = tnl->vb.ResultPtr[i]->size;
tnl->last_result_stride[i] = tnl->vb.ResultPtr[i]->stride;
tnl->pipeline.output_changes |= 1<<i;
}
}
if (tnl->pipeline.output_changes)
tnl->Driver.NotifyOutputChanges( ctx, tnl->pipeline.output_changes );
return tnl->pipeline.output_changes;
#else
return ~0;
#endif
}
/**
* START/END_FAST_MATH macros:
*
* START_FAST_MATH: Set x86 FPU to faster, 32-bit precision mode (and save
* original mode to a temporary).
* END_FAST_MATH: Restore x86 FPU to original mode.
*/
#if defined(__GNUC__) && defined(__i386__)
/*
* Set the x86 FPU control word to guarentee only 32 bits of precision
* are stored in registers. Allowing the FPU to store more introduces
* differences between situations where numbers are pulled out of memory
* vs. situations where the compiler is able to optimize register usage.
*
* In the worst case, we force the compiler to use a memory access to
* truncate the float, by specifying the 'volatile' keyword.
*/
/* Hardware default: All exceptions masked, extended double precision,
* round to nearest (IEEE compliant):
*/
#define DEFAULT_X86_FPU 0x037f
/* All exceptions masked, single precision, round to nearest:
*/
#define FAST_X86_FPU 0x003f
/* The fldcw instruction will cause any pending FP exceptions to be
* raised prior to entering the block, and we clear any pending
* exceptions before exiting the block. Hence, asm code has free
* reign over the FPU while in the fast math block.
*/
#if defined(NO_FAST_MATH)
#define START_FAST_MATH(x) \
do { \
static GLuint mask = DEFAULT_X86_FPU; \
__asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
__asm__ ( "fldcw %0" : : "m" (mask) ); \
} while (0)
#else
#define START_FAST_MATH(x) \
do { \
static GLuint mask = FAST_X86_FPU; \
__asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
__asm__ ( "fldcw %0" : : "m" (mask) ); \
} while (0)
#endif
/* Restore original FPU mode, and clear any exceptions that may have
* occurred in the FAST_MATH block.
*/
#define END_FAST_MATH(x) \
do { \
__asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \
} while (0)
#elif defined(_MSC_VER) && defined(_M_IX86)
#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */
#define FAST_X86_FPU 0x003f /* See GCC comments above */
#if defined(NO_FAST_MATH)
#define START_FAST_MATH(x) do {\
static GLuint mask = DEFAULT_X86_FPU;\
__asm fnstcw word ptr [x]\
__asm fldcw word ptr [mask]\
} while(0)
#else
#define START_FAST_MATH(x) do {\
static GLuint mask = FAST_X86_FPU;\
__asm fnstcw word ptr [x]\
__asm fldcw word ptr [mask]\
} while(0)
#endif
#define END_FAST_MATH(x) do {\
__asm fnclex\
__asm fldcw word ptr [x]\
} while(0)
#else
#define START_FAST_MATH(x) x = 0
#define END_FAST_MATH(x) (void)(x)
#endif
void _tnl_run_pipeline( struct gl_context *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
unsigned short __tmp;
GLuint i;
if (!tnl->vb.Count)
return;
/* Check for changed input sizes or change in stride to/from zero
* (ie const or non-const).
*/
if (check_input_changes( ctx ) || tnl->pipeline.new_state) {
if (ctx->VertexProgram._MaintainTnlProgram)
_tnl_UpdateFixedFunctionProgram( ctx );
for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
if (s->validate)
s->validate( ctx, s );
}
tnl->pipeline.new_state = 0;
tnl->pipeline.input_changes = 0;
/* Pipeline can only change its output in response to either a
* statechange or an input size/stride change. No other changes
* are allowed.
*/
if (check_output_changes( ctx ))
_tnl_notify_pipeline_output_change( ctx );
}
#ifndef _OPENMP
/* Don't adjust FPU precision mode in case multiple threads are to be used.
* This would require that the additional threads also changed the FPU mode
* which is quite a mess as this had to be done in all parallelized sections;
* otherwise the master thread and all other threads are running in different
* modes, producing inconsistent results.
* Note that all x64 implementations don't define/use START_FAST_MATH, so
* this is "hack" is only used in i386 mode
*/
START_FAST_MATH(__tmp);
#endif
for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
if (!s->run( ctx, s ))
break;
}
#ifndef _OPENMP
END_FAST_MATH(__tmp);
#endif
}
/* The default pipeline. This is useful for software rasterizers, and
* simple hardware rasterizers. For customization, I don't recommend
* tampering with the internals of these stages in the way that
* drivers did in Mesa 3.4. These stages are basically black boxes,
* and should be left intact.
*
* To customize the pipeline, consider:
*
* - removing redundant stages (making sure that the software rasterizer
* can cope with this on fallback paths). An example is fog
* coordinate generation, which is not required in the FX driver.
*
* - replacing general-purpose machine-independent stages with
* general-purpose machine-specific stages. There is no example of
* this to date, though it must be borne in mind that all subsequent
* stages that reference the output of the new stage must cope with
* any machine-specific data introduced. This may not be easy
* unless there are no such stages (ie the new stage is the last in
* the pipe).
*
* - inserting optimized (but specialized) stages ahead of the
* general-purpose fallback implementation. For example, the old
* fastpath mechanism, which only works when the VB->Elts input is
* available, can be duplicated by placing the fastpath stage at the
* head of this pipeline. Such specialized stages are currently
* constrained to have no outputs (ie. they must either finish the *
* pipeline by returning GL_FALSE from run(), or do nothing).
*
* Some work can be done to lift some of the restrictions in the final
* case, if it becomes necessary to do so.
*/
const struct tnl_pipeline_stage *_tnl_default_pipeline[] = {
&_tnl_vertex_transform_stage,
&_tnl_normal_transform_stage,
&_tnl_lighting_stage,
&_tnl_texgen_stage,
&_tnl_texture_transform_stage,
&_tnl_point_attenuation_stage,
&_tnl_vertex_program_stage,
&_tnl_fog_coordinate_stage,
&_tnl_render_stage,
NULL
};
const struct tnl_pipeline_stage *_tnl_vp_pipeline[] = {
&_tnl_vertex_program_stage,
&_tnl_render_stage,
NULL
};

View File

@ -1,73 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#ifndef _T_PIPELINE_H_
#define _T_PIPELINE_H_
#include "main/mtypes.h"
#include "t_context.h"
extern void _tnl_run_pipeline( struct gl_context *ctx );
extern void _tnl_destroy_pipeline( struct gl_context *ctx );
extern void _tnl_install_pipeline( struct gl_context *ctx,
const struct tnl_pipeline_stage **stages );
/* These are implemented in the t_vb_*.c files:
*/
extern const struct tnl_pipeline_stage _tnl_vertex_transform_stage;
extern const struct tnl_pipeline_stage _tnl_normal_transform_stage;
extern const struct tnl_pipeline_stage _tnl_lighting_stage;
extern const struct tnl_pipeline_stage _tnl_fog_coordinate_stage;
extern const struct tnl_pipeline_stage _tnl_texgen_stage;
extern const struct tnl_pipeline_stage _tnl_texture_transform_stage;
extern const struct tnl_pipeline_stage _tnl_point_attenuation_stage;
extern const struct tnl_pipeline_stage _tnl_vertex_program_stage;
extern const struct tnl_pipeline_stage _tnl_render_stage;
/* Shorthand to plug in the default pipeline:
*/
extern const struct tnl_pipeline_stage *_tnl_default_pipeline[];
extern const struct tnl_pipeline_stage *_tnl_vp_pipeline[];
/* Convenience routines provided by t_vb_render.c:
*/
extern tnl_render_func _tnl_render_tab_elts[];
extern tnl_render_func _tnl_render_tab_verts[];
extern void _tnl_RenderClippedPolygon( struct gl_context *ctx,
const GLuint *elts, GLuint n );
extern void _tnl_RenderClippedLine( struct gl_context *ctx, GLuint ii, GLuint jj );
#endif

View File

@ -1,267 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
/* Helper for drivers which find themselves rendering a range of
* indices starting somewhere above zero. Typically the application
* is issuing multiple DrawArrays() or DrawElements() to draw
* successive primitives layed out linearly in the vertex arrays.
* Unless the vertex arrays are all in a VBO, the OpenGL semantics
* imply that we need to re-upload the vertex data on each draw call.
* In that case, we want to avoid starting the upload at zero, as it
* will mean every draw call uploads an increasing amount of not-used
* vertex data. Worse - in the software tnl module, all those
* vertices will be transformed and lit.
*
* If we just upload the new data, however, the indices will be
* incorrect as we tend to upload each set of vertex data to a new
* region.
*
* This file provides a helper to adjust the arrays, primitives and
* indices of a draw call so that it can be re-issued with a min_index
* of zero.
*/
#include <stdio.h>
#include "main/bufferobj.h"
#include "main/errors.h"
#include "main/glheader.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "vbo/vbo.h"
#include "t_rebase.h"
#define REBASE(TYPE) \
static void *rebase_##TYPE(const void *ptr, \
unsigned start, \
unsigned count, \
TYPE min_index) \
{ \
const TYPE *in = (TYPE *)ptr; \
TYPE *tmp_indices = malloc((start + count) * sizeof(TYPE)); \
\
if (tmp_indices == NULL) { \
_mesa_error_no_memory(__func__); \
return NULL; \
} \
\
for (unsigned i = 0; i < count; i++) \
tmp_indices[start + i] = in[start + i] - min_index; \
\
return (void *)tmp_indices; \
}
REBASE(GLuint)
REBASE(GLushort)
REBASE(GLubyte)
/* Adjust primitives, indices and vertex definitions so that min_index
* becomes zero. There are lots of reasons for wanting to do this, eg:
*
* Software tnl:
* - any time min_index != 0, otherwise unused vertices lower than
* min_index will be transformed.
*
* Hardware tnl:
* - if ib != NULL and min_index != 0, otherwise vertices lower than
* min_index will be uploaded. Requires adjusting index values.
*
* - if ib == NULL and min_index != 0, just for convenience so this doesn't
* have to be handled within the driver.
*
* Hardware tnl with VBO support:
* - as above, but only when vertices are not (all?) in VBO's.
* - can't save time by trying to upload half a vbo - typically it is
* all or nothing.
*/
void t_rebase_prims(struct gl_context *ctx,
const struct tnl_vertex_array *arrays,
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index,
GLuint num_instances,
GLuint base_instance,
tnl_draw_func draw)
{
struct gl_array_attributes tmp_attribs[VERT_ATTRIB_MAX];
struct tnl_vertex_array tmp_arrays[VERT_ATTRIB_MAX];
struct _mesa_index_buffer tmp_ib;
struct _mesa_prim *tmp_prims = NULL;
void *tmp_indices = NULL;
GLuint i;
assert(min_index != 0);
if (0)
printf("%s %d..%d\n", __func__, min_index, max_index);
/* XXX this path is disabled for now.
* There's rendering corruption in some apps when it's enabled.
*/
if (0 && ib && ctx->Extensions.ARB_draw_elements_base_vertex) {
/* If we can just tell the hardware or the TNL to interpret our indices
* with a different base, do so.
*/
tmp_prims = malloc(sizeof(*prim) * nr_prims);
if (tmp_prims == NULL) {
_mesa_error_no_memory(__func__);
return;
}
for (i = 0; i < nr_prims; i++) {
tmp_prims[i] = prim[i];
tmp_prims[i].basevertex -= min_index;
}
prim = tmp_prims;
} else if (ib) {
unsigned start = prim[0].start;
for (i = 1; i < nr_prims; i++) {
if (prim[i].start != start) {
if (0) {
printf("%s recursing due to mismatched start "
"(prim[0].start = %u vs. prim[%u].start = %u)\n",
__func__, start, i, prim[i].start);
}
t_rebase_prims(ctx, arrays, &prim[0], i, ib, min_index,
max_index, num_instances, base_instance, draw);
t_rebase_prims(ctx, arrays, &prim[i], nr_prims - i, ib, min_index,
max_index, num_instances, base_instance, draw);
return;
}
}
/* Unfortunately need to adjust each index individually.
*/
bool map_ib = false;
const void *ptr;
if (ib->obj) {
if (!ib->obj->Mappings[MAP_INTERNAL].Pointer) {
ctx->Driver.MapBufferRange(ctx, 0, ib->obj->Size, GL_MAP_READ_BIT,
ib->obj, MAP_INTERNAL);
map_ib = true;
}
ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr);
} else
ptr = ib->ptr;
/* Some users might prefer it if we translated elements to GLuints here.
* Others wouldn't...
*/
switch (ib->index_size_shift) {
case 2:
tmp_indices = rebase_GLuint(ptr, start, ib->count, min_index);
break;
case 1:
tmp_indices = rebase_GLushort(ptr, start, ib->count, min_index);
break;
case 0:
tmp_indices = rebase_GLubyte(ptr, start, ib->count, min_index);
break;
}
if (map_ib)
ctx->Driver.UnmapBuffer(ctx, ib->obj, MAP_INTERNAL);
if (tmp_indices == NULL)
return;
tmp_ib.obj = NULL;
tmp_ib.ptr = tmp_indices;
tmp_ib.count = ib->count;
tmp_ib.index_size_shift = ib->index_size_shift;
ib = &tmp_ib;
}
else {
/* Otherwise the primitives need adjustment. */
tmp_prims = malloc(sizeof(*prim) * nr_prims);
if (tmp_prims == NULL) {
_mesa_error_no_memory(__func__);
return;
}
for (i = 0; i < nr_prims; i++) {
/* If this fails, it could indicate an application error: */
assert(prim[i].start >= min_index);
tmp_prims[i] = prim[i];
tmp_prims[i].start -= min_index;
}
prim = tmp_prims;
}
/* Just need to adjust the pointer values on each incoming array.
* This works for VBO and non-vbo rendering and shouldn't pesimize
* VBO-based upload schemes. However this may still not be a fast
* path for hardware tnl for VBO based rendering as most machines
* will be happier if you just specify a starting vertex value in
* each primitive.
*
* For drivers with hardware tnl, you only want to do this if you
* are forced to, eg non-VBO indexed rendering with start != 0.
*/
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
tmp_attribs[i] = *(arrays[i].VertexAttrib);
tmp_arrays[i].BufferBinding = arrays[i].BufferBinding;
tmp_arrays[i].VertexAttrib = &tmp_attribs[i];
if (arrays[i].BufferBinding->BufferObj)
tmp_attribs[i].RelativeOffset +=
min_index * arrays[i].BufferBinding->Stride;
else
tmp_attribs[i].Ptr += min_index * arrays[i].BufferBinding->Stride;
}
/* Re-issue the draw call. */
draw(ctx,
tmp_arrays,
prim,
nr_prims,
ib,
GL_TRUE,
0,
max_index - min_index,
num_instances, base_instance);
free(tmp_indices);
free(tmp_prims);
}

View File

@ -1,41 +0,0 @@
/*
* mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _T_REBASE_H_
#define _T_REBASE_H_
#include "tnl.h"
void t_rebase_prims( struct gl_context *ctx,
const struct tnl_vertex_array *arrays,
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index,
GLuint num_instances,
GLuint base_instance,
tnl_draw_func draw );
#endif

View File

@ -1,162 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
/* Deal with hardware and/or swtnl maximums:
* - maximum number of vertices in buffer
* - maximum number of elements (maybe zero)
*
* The maximums may vary with opengl state (eg if a larger hardware
* vertex is required in this state, the maximum number of vertices
* may be smaller than in another state).
*
* We want buffer splitting to be a convenience function for the code
* actually drawing the primitives rather than a system-wide maximum,
* otherwise it is hard to avoid pessimism.
*
* For instance, if a driver has no hardware limits on vertex buffer
* dimensions, it would not ordinarily want to split vbos. But if
* there is an unexpected fallback, eg memory manager fails to upload
* textures, it will want to pass the drawing commands onto swtnl,
* which does have limitations. A convenience function allows swtnl
* to split the drawing and vbos internally without imposing its
* limitations on drivers which want to use it as a fallback path.
*/
#include "main/glheader.h"
#include "main/mtypes.h"
#include "vbo/vbo.h"
#include "t_split.h"
/* True if a primitive can be split without copying of vertices, false
* otherwise.
*/
GLboolean
_tnl_split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
{
switch (mode) {
case GL_POINTS:
*first = 1;
*incr = 1;
return GL_TRUE;
case GL_LINES:
*first = 2;
*incr = 2;
return GL_TRUE;
case GL_LINE_STRIP:
*first = 2;
*incr = 1;
return GL_TRUE;
case GL_TRIANGLES:
*first = 3;
*incr = 3;
return GL_TRUE;
case GL_TRIANGLE_STRIP:
*first = 3;
*incr = 1;
return GL_TRUE;
case GL_QUADS:
*first = 4;
*incr = 4;
return GL_TRUE;
case GL_QUAD_STRIP:
*first = 4;
*incr = 2;
return GL_TRUE;
default:
*first = 0;
*incr = 1; /* so that count % incr works */
return GL_FALSE;
}
}
void
_tnl_split_prims(struct gl_context *ctx,
const struct tnl_vertex_array arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index,
GLuint num_instances,
GLuint base_instance,
tnl_draw_func draw,
const struct split_limits *limits)
{
if (ib) {
if (limits->max_indices == 0) {
/* Could traverse the indices, re-emitting vertices in turn.
* But it's hard to see why this case would be needed - for
* software tnl, it is better to convert to non-indexed
* rendering after transformation is complete. Are there any devices
* with hardware tnl that cannot do indexed rendering?
*
* For now, this path is disabled.
*/
assert(0);
}
else if (max_index - min_index >= limits->max_verts) {
/* The vertex buffers are too large for hardware (or the
* swtnl module). Traverse the indices, re-emitting vertices
* in turn. Use a vertex cache to preserve some of the
* sharing from the original index list.
*/
_tnl_split_copy(ctx, arrays, prim, nr_prims, ib, draw, limits);
}
else if (ib->count > limits->max_indices) {
/* The index buffer is too large for hardware. Try to split
* on whole-primitive boundaries, otherwise try to split the
* individual primitives.
*/
_tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
num_instances, base_instance, draw, limits);
}
else {
/* Why were we called? */
assert(0);
}
}
else {
if (max_index - min_index >= limits->max_verts) {
/* The vertex buffer is too large for hardware (or the swtnl
* module). Try to split on whole-primitive boundaries,
* otherwise try to split the individual primitives.
*/
_tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
num_instances, base_instance, draw, limits);
}
else {
/* Why were we called? */
assert(0);
}
}
}

View File

@ -1,74 +0,0 @@
/*
* mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \brief VBO builder module datatypes and definitions.
* \author Keith Whitwell
*/
/**
* \mainpage The TNL splitter
*
* This is the private data used internally to the _tnl_split_prims()
* helper function. Nobody outside the _tnl_split* files needs to
* include or know about this structure.
*/
#ifndef _TNL_SPLIT_H
#define _TNL_SPLIT_H
#include "tnl.h"
/* True if a primitive can be split without copying of vertices, false
* otherwise.
*/
GLboolean
_tnl_split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr);
void
_tnl_split_inplace(struct gl_context *ctx,
const struct tnl_vertex_array arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint num_instances,
GLuint base_instance,
tnl_draw_func draw,
const struct split_limits *limits);
/* Requires ib != NULL:
*/
void
_tnl_split_copy(struct gl_context *ctx,
const struct tnl_vertex_array arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
tnl_draw_func draw,
const struct split_limits *limits);
#endif

View File

@ -1,637 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
/* Split indexed primitives with per-vertex copying.
*/
#include <stdio.h>
#include "main/glheader.h"
#include "main/bufferobj.h"
#include "main/glformats.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/varray.h"
#include "vbo/vbo.h"
#include "t_split.h"
#include "tnl.h"
#define ELT_TABLE_SIZE 16
/**
* Used for vertex-level splitting of indexed buffers. Note that
* non-indexed primitives may be converted to indexed in some cases
* (eg loops, fans) in order to use this splitting path.
*/
struct copy_context {
struct gl_context *ctx;
const struct tnl_vertex_array *array;
const struct _mesa_prim *prim;
GLuint nr_prims;
const struct _mesa_index_buffer *ib;
tnl_draw_func draw;
const struct split_limits *limits;
struct {
GLuint attr;
GLuint size;
const struct tnl_vertex_array *array;
const GLubyte *src_ptr;
struct gl_vertex_buffer_binding dstbinding;
struct gl_array_attributes dstattribs;
} varying[VERT_ATTRIB_MAX];
GLuint nr_varying;
struct tnl_vertex_array dstarray[VERT_ATTRIB_MAX];
struct _mesa_index_buffer dstib;
GLuint *translated_elt_buf;
const GLuint *srcelt;
/** A baby hash table to avoid re-emitting (some) duplicate
* vertices when splitting indexed primitives.
*/
struct {
GLuint in;
GLuint out;
} vert_cache[ELT_TABLE_SIZE];
GLuint vertex_size;
GLubyte *dstbuf;
GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */
GLuint dstbuf_size; /**< in vertices */
GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value
* in dstelt. Our MaxIndex.
*/
GLuint *dstelt;
GLuint dstelt_nr;
GLuint dstelt_size;
#define MAX_PRIM 32
struct _mesa_prim dstprim[MAX_PRIM];
GLuint dstprim_nr;
};
/**
* Shallow copy one vertex array to another.
*/
static inline void
copy_vertex_array(struct tnl_vertex_array *dst,
const struct tnl_vertex_array *src)
{
dst->VertexAttrib = src->VertexAttrib;
dst->BufferBinding = src->BufferBinding;
}
/**
* Starts returning true slightly before the buffer fills, to ensure
* that there is sufficient room for any remaining vertices to finish
* off the prim:
*/
static GLboolean
check_flush(struct copy_context *copy)
{
GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
if (GL_TRIANGLE_STRIP == mode &&
copy->dstelt_nr & 1) { /* see bug9962 */
return GL_FALSE;
}
if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
return GL_TRUE;
if (copy->dstelt_nr + 4 > copy->dstelt_size)
return GL_TRUE;
return GL_FALSE;
}
/**
* Dump the parameters/info for a vbo->draw() call.
*/
static void
dump_draw_info(const struct tnl_vertex_array *arrays,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib)
{
GLuint i, j;
printf("VBO Draw:\n");
for (i = 0; i < nr_prims; i++) {
printf("Prim %u of %u\n", i, nr_prims);
printf(" Prim mode 0x%x\n", prims[i].mode);
printf(" IB: %p\n", (void*) ib);
for (j = 0; j < VERT_ATTRIB_MAX; j++) {
const struct tnl_vertex_array *array = &arrays[j];
const struct gl_vertex_buffer_binding *binding
= array->BufferBinding;
const struct gl_array_attributes *attrib = array->VertexAttrib;
const GLubyte *ptr = _mesa_vertex_attrib_address(attrib, binding);
printf(" array %d at %p:\n", j, (void*) &arrays[j]);
printf(" ptr %p, size %d, type 0x%x, stride %d\n",
ptr, attrib->Format.Size, attrib->Format.Type, binding->Stride);
if (0) {
GLint k = prims[i].start + prims[i].count - 1;
GLfloat *last = (GLfloat *) (ptr + binding->Stride * k);
printf(" last: %f %f %f\n",
last[0], last[1], last[2]);
}
}
}
}
static void
flush(struct copy_context *copy)
{
struct gl_context *ctx = copy->ctx;
GLuint i;
/* Set some counters:
*/
copy->dstib.count = copy->dstelt_nr;
#if 0
dump_draw_info(copy->dstarray,
copy->dstprim,
copy->dstprim_nr,
&copy->dstib);
#else
(void) dump_draw_info;
#endif
copy->draw(ctx,
copy->dstarray,
copy->dstprim,
copy->dstprim_nr,
&copy->dstib,
GL_TRUE,
0,
copy->dstbuf_nr - 1,
1,
0);
/* Reset all pointers:
*/
copy->dstprim_nr = 0;
copy->dstelt_nr = 0;
copy->dstbuf_nr = 0;
copy->dstptr = copy->dstbuf;
/* Clear the vertex cache:
*/
for (i = 0; i < ELT_TABLE_SIZE; i++)
copy->vert_cache[i].in = ~0;
}
/**
* Called at begin of each primitive during replay.
*/
static void
begin(struct copy_context *copy, GLenum mode, GLboolean begin_flag)
{
struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
prim->mode = mode;
prim->begin = begin_flag;
}
/**
* Use a hashtable to attempt to identify recently-emitted vertices
* and avoid re-emitting them.
*/
static GLuint
elt(struct copy_context *copy, GLuint elt_idx)
{
GLuint elt = copy->srcelt[elt_idx] + copy->prim->basevertex;
GLuint slot = elt & (ELT_TABLE_SIZE-1);
/* Look up the incoming element in the vertex cache. Re-emit if
* necessary.
*/
if (copy->vert_cache[slot].in != elt) {
GLubyte *csr = copy->dstptr;
GLuint i;
for (i = 0; i < copy->nr_varying; i++) {
const struct tnl_vertex_array *srcarray = copy->varying[i].array;
const struct gl_vertex_buffer_binding* srcbinding
= srcarray->BufferBinding;
const GLubyte *srcptr
= copy->varying[i].src_ptr + elt * srcbinding->Stride;
memcpy(csr, srcptr, copy->varying[i].size);
csr += copy->varying[i].size;
#ifdef NAN_CHECK
if (srcarray->Format.Type == GL_FLOAT) {
GLuint k;
GLfloat *f = (GLfloat *) srcptr;
for (k = 0; k < srcarray->Size; k++) {
assert(!util_is_inf_or_nan(f[k]));
assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
}
}
#endif
if (0) {
const GLuint *f = (const GLuint *)srcptr;
GLuint j;
printf(" varying %d: ", i);
for (j = 0; j < copy->varying[i].size / 4; j++)
printf("%x ", f[j]);
printf("\n");
}
}
copy->vert_cache[slot].in = elt;
copy->vert_cache[slot].out = copy->dstbuf_nr++;
copy->dstptr += copy->vertex_size;
assert(csr == copy->dstptr);
assert(copy->dstptr == (copy->dstbuf +
copy->dstbuf_nr * copy->vertex_size));
}
copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
return check_flush(copy);
}
/**
* Called at end of each primitive during replay.
*/
static void
end(struct copy_context *copy, GLboolean end_flag)
{
struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
prim->end = end_flag;
prim->count = copy->dstelt_nr - prim->start;
if (++copy->dstprim_nr == MAX_PRIM || check_flush(copy)) {
flush(copy);
}
}
static void
replay_elts(struct copy_context *copy)
{
GLuint i, j, k;
GLboolean split;
for (i = 0; i < copy->nr_prims; i++) {
const struct _mesa_prim *prim = &copy->prim[i];
const GLuint start = prim->start;
GLuint first, incr;
switch (prim->mode) {
case GL_LINE_LOOP:
/* Convert to linestrip and emit the final vertex explicitly,
* but only in the resultant strip that requires it.
*/
j = 0;
while (j != prim->count) {
begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
for (split = GL_FALSE; j != prim->count && !split; j++)
split = elt(copy, start + j);
if (j == prim->count) {
/* Done, emit final line. Split doesn't matter as
* it is always raised a bit early so we can emit
* the last verts if necessary!
*/
if (prim->end)
(void)elt(copy, start + 0);
end(copy, prim->end);
}
else {
/* Wrap
*/
assert(split);
end(copy, 0);
j--;
}
}
break;
case GL_TRIANGLE_FAN:
case GL_POLYGON:
j = 2;
while (j != prim->count) {
begin(copy, prim->mode, prim->begin && j == 0);
split = elt(copy, start+0);
assert(!split);
split = elt(copy, start+j-1);
assert(!split);
for (; j != prim->count && !split; j++)
split = elt(copy, start+j);
end(copy, prim->end && j == prim->count);
if (j != prim->count) {
/* Wrapped the primitive, need to repeat some vertices:
*/
j -= 1;
}
}
break;
default:
(void)_tnl_split_prim_inplace(prim->mode, &first, &incr);
j = 0;
while (j != prim->count) {
begin(copy, prim->mode, prim->begin && j == 0);
split = 0;
for (k = 0; k < first; k++, j++)
split |= elt(copy, start+j);
assert(!split);
for (; j != prim->count && !split;)
for (k = 0; k < incr; k++, j++)
split |= elt(copy, start+j);
end(copy, prim->end && j == prim->count);
if (j != prim->count) {
/* Wrapped the primitive, need to repeat some vertices:
*/
assert(j > first - incr);
j -= (first - incr);
}
}
break;
}
}
if (copy->dstprim_nr)
flush(copy);
}
static void
replay_init(struct copy_context *copy)
{
struct gl_context *ctx = copy->ctx;
GLuint i;
GLuint offset;
const GLvoid *srcptr;
/* Make a list of varying attributes and their vbo's. Also
* calculate vertex size.
*/
copy->vertex_size = 0;
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
const struct tnl_vertex_array *array = &copy->array[i];
const struct gl_vertex_buffer_binding *binding = array->BufferBinding;
if (binding->Stride == 0) {
copy_vertex_array(&copy->dstarray[i], array);
}
else {
const struct gl_array_attributes *attrib = array->VertexAttrib;
struct gl_buffer_object *vbo = binding->BufferObj;
const GLubyte *ptr = _mesa_vertex_attrib_address(attrib, binding);
GLuint j = copy->nr_varying++;
copy->varying[j].attr = i;
copy->varying[j].array = &copy->array[i];
copy->varying[j].size = attrib->Format._ElementSize;
copy->vertex_size += attrib->Format._ElementSize;
if (vbo) {
if (!_mesa_bufferobj_mapped(vbo, MAP_INTERNAL)) {
ctx->Driver.MapBufferRange(ctx, 0, vbo->Size, GL_MAP_READ_BIT, vbo,
MAP_INTERNAL);
}
copy->varying[j].src_ptr =
ADD_POINTERS(vbo->Mappings[MAP_INTERNAL].Pointer, ptr);
} else {
copy->varying[j].src_ptr = ptr;
}
copy->dstarray[i].VertexAttrib = &copy->varying[j].dstattribs;
copy->dstarray[i].BufferBinding = &copy->varying[j].dstbinding;
}
}
/* There must always be an index buffer. Currently require the
* caller convert non-indexed prims to indexed. Could alternately
* do it internally.
*/
if (copy->ib->obj) {
if (!_mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL))
ctx->Driver.MapBufferRange(ctx, 0, copy->ib->obj->Size, GL_MAP_READ_BIT,
copy->ib->obj, MAP_INTERNAL);
srcptr = (const GLubyte *)
ADD_POINTERS(copy->ib->obj->Mappings[MAP_INTERNAL].Pointer,
copy->ib->ptr);
} else
srcptr = copy->ib->ptr;
switch (copy->ib->index_size_shift) {
case 0:
copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
copy->srcelt = copy->translated_elt_buf;
for (i = 0; i < copy->ib->count; i++)
copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
break;
case 1:
copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
copy->srcelt = copy->translated_elt_buf;
for (i = 0; i < copy->ib->count; i++)
copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
break;
case 2:
copy->translated_elt_buf = NULL;
copy->srcelt = (const GLuint *)srcptr;
break;
}
/* Figure out the maximum allowed vertex buffer size:
*/
if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
copy->dstbuf_size = copy->limits->max_verts;
}
else {
copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
}
/* Allocate an output vertex buffer:
*
* XXX: This should be a VBO!
*/
copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size);
copy->dstptr = copy->dstbuf;
/* Setup new vertex arrays to point into the output buffer:
*/
for (offset = 0, i = 0; i < copy->nr_varying; i++) {
const struct tnl_vertex_array *src = copy->varying[i].array;
const struct gl_array_attributes *srcattr = src->VertexAttrib;
struct tnl_vertex_array *dst = &copy->dstarray[copy->varying[i].attr];
struct gl_vertex_buffer_binding *dstbind = &copy->varying[i].dstbinding;
struct gl_array_attributes *dstattr = &copy->varying[i].dstattribs;
dstattr->Format = srcattr->Format;
dstattr->Ptr = copy->dstbuf + offset;
dstbind->Stride = copy->vertex_size;
dstbind->BufferObj = NULL;
dst->BufferBinding = dstbind;
dst->VertexAttrib = dstattr;
offset += copy->varying[i].size;
}
/* Allocate an output element list:
*/
copy->dstelt_size = MIN2(65536, copy->ib->count * 2 + 3);
copy->dstelt_size = MIN2(copy->dstelt_size, copy->limits->max_indices);
copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size);
copy->dstelt_nr = 0;
/* Setup the new index buffer to point to the allocated element
* list:
*/
copy->dstib.count = 0; /* duplicates dstelt_nr */
copy->dstib.index_size_shift = 2;
copy->dstib.obj = NULL;
copy->dstib.ptr = copy->dstelt;
}
/**
* Free up everything allocated during split/replay.
*/
static void
replay_finish(struct copy_context *copy)
{
struct gl_context *ctx = copy->ctx;
GLuint i;
/* Free our vertex and index buffers */
free(copy->translated_elt_buf);
free(copy->dstbuf);
free(copy->dstelt);
/* Unmap VBO's */
for (i = 0; i < copy->nr_varying; i++) {
struct gl_buffer_object *vbo =
copy->varying[i].array->BufferBinding->BufferObj;
if (vbo && _mesa_bufferobj_mapped(vbo, MAP_INTERNAL))
ctx->Driver.UnmapBuffer(ctx, vbo, MAP_INTERNAL);
}
/* Unmap index buffer */
if (copy->ib->obj &&
_mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL)) {
ctx->Driver.UnmapBuffer(ctx, copy->ib->obj, MAP_INTERNAL);
}
}
/**
* Split VBO into smaller pieces, draw the pieces.
*/
void
_tnl_split_copy(struct gl_context *ctx,
const struct tnl_vertex_array *arrays,
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
tnl_draw_func draw,
const struct split_limits *limits)
{
struct copy_context copy;
GLuint i, this_nr_prims;
for (i = 0; i < nr_prims;) {
/* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
* will rebase the elements to the basevertex, and we'll only
* emit strings of prims with the same basevertex in one draw call.
*/
for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
this_nr_prims++) {
if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
break;
}
memset(&copy, 0, sizeof(copy));
/* Require indexed primitives:
*/
assert(ib);
copy.ctx = ctx;
copy.array = arrays;
copy.prim = &prim[i];
copy.nr_prims = this_nr_prims;
copy.ib = ib;
copy.draw = draw;
copy.limits = limits;
/* Clear the vertex cache:
*/
for (i = 0; i < ELT_TABLE_SIZE; i++)
copy.vert_cache[i].in = ~0;
replay_init(&copy);
replay_elts(&copy);
replay_finish(&copy);
}
}

View File

@ -1,296 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/enums.h"
#include "vbo/vbo.h"
#include "t_split.h"
#define MAX_PRIM 32
/* Used for splitting without copying. No attempt is made to handle
* too large indexed vertex buffers: In general you need to copy to do
* that.
*/
struct split_context {
struct gl_context *ctx;
const struct tnl_vertex_array *array;
const struct _mesa_prim *prim;
GLuint nr_prims;
const struct _mesa_index_buffer *ib;
GLuint min_index;
GLuint max_index;
GLuint num_instances;
GLuint base_instance;
tnl_draw_func draw;
const struct split_limits *limits;
GLuint limit;
struct _mesa_prim dstprim[MAX_PRIM];
GLuint dstprim_nr;
};
static void
flush_vertex( struct split_context *split)
{
struct gl_context *ctx = split->ctx;
struct _mesa_index_buffer ib;
GLuint i;
if (!split->dstprim_nr)
return;
if (split->ib) {
ib = *split->ib;
ib.count = split->max_index - split->min_index + 1;
ib.ptr = (const void *)((const char *)ib.ptr +
(split->min_index << ib.index_size_shift));
/* Rebase the primitives to save index buffer entries. */
for (i = 0; i < split->dstprim_nr; i++)
split->dstprim[i].start -= split->min_index;
}
assert(split->max_index >= split->min_index);
split->draw(ctx,
split->array,
split->dstprim,
split->dstprim_nr,
split->ib ? &ib : NULL,
!split->ib,
split->min_index,
split->max_index,
split->num_instances,
split->base_instance);
split->dstprim_nr = 0;
split->min_index = ~0;
split->max_index = 0;
}
static struct _mesa_prim *
next_outprim(struct split_context *split)
{
if (split->dstprim_nr == MAX_PRIM-1) {
flush_vertex(split);
}
{
struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
memset(prim, 0, sizeof(*prim));
return prim;
}
}
static void
update_index_bounds(struct split_context *split,
const struct _mesa_prim *prim)
{
split->min_index = MIN2(split->min_index, prim->start);
split->max_index = MAX2(split->max_index, prim->start + prim->count - 1);
}
/* Return the maximum amount of vertices that can be emitted for a
* primitive starting at 'prim->start', depending on the previous
* index bounds.
*/
static GLuint
get_max_vertices(struct split_context *split,
const struct _mesa_prim *prim)
{
if ((prim->start > split->min_index &&
prim->start - split->min_index >= split->limit) ||
(prim->start < split->max_index &&
split->max_index - prim->start >= split->limit))
/* "prim" starts too far away from the old range. */
return 0;
return MIN2(split->min_index, prim->start) + split->limit - prim->start;
}
/* Break large primitives into smaller ones. If not possible, convert
* the primitive to indexed and pass to split_elts().
*/
static void
split_prims(struct split_context *split)
{
GLuint i;
for (i = 0; i < split->nr_prims; i++) {
const struct _mesa_prim *prim = &split->prim[i];
GLuint first, incr;
GLboolean split_inplace =
_tnl_split_prim_inplace(prim->mode, &first, &incr);
GLuint available = get_max_vertices(split, prim);
GLuint count = prim->count - (prim->count - first) % incr;
if (prim->count < first)
continue;
if ((available < count && !split_inplace) ||
(available < first && split_inplace)) {
flush_vertex(split);
available = get_max_vertices(split, prim);
}
if (available >= count) {
struct _mesa_prim *outprim = next_outprim(split);
*outprim = *prim;
update_index_bounds(split, outprim);
}
else if (split_inplace) {
GLuint j, nr;
for (j = 0 ; j < count ;) {
GLuint remaining = count - j;
struct _mesa_prim *outprim = next_outprim(split);
nr = MIN2(available, remaining);
nr -= (nr - first) % incr;
outprim->mode = prim->mode;
outprim->begin = (j == 0 && prim->begin);
outprim->end = (nr == remaining && prim->end);
outprim->start = prim->start + j;
outprim->count = nr;
update_index_bounds(split, outprim);
if (nr == remaining) {
/* Finished */
j += nr;
}
else {
/* Wrapped the primitive */
j += nr - (first - incr);
flush_vertex(split);
available = get_max_vertices(split, prim);
}
}
}
else if (split->ib == NULL) {
/* XXX: could at least send the first max_verts off from the
* inplace buffers.
*/
/* else convert to indexed primitive and pass to split_elts,
* which will do the necessary copying and turn it back into a
* vertex primitive for rendering...
*/
struct _mesa_index_buffer ib;
struct _mesa_prim tmpprim;
GLuint *elts = malloc(count * sizeof(GLuint));
GLuint j;
for (j = 0; j < count; j++)
elts[j] = prim->start + j;
ib.count = count;
ib.index_size_shift = 2;
ib.obj = NULL;
ib.ptr = elts;
tmpprim = *prim;
tmpprim.start = 0;
tmpprim.count = count;
flush_vertex(split);
_tnl_split_copy(split->ctx,
split->array,
&tmpprim, 1,
&ib,
split->draw,
split->limits);
free(elts);
}
else {
flush_vertex(split);
_tnl_split_copy(split->ctx,
split->array,
prim, 1,
split->ib,
split->draw,
split->limits);
}
}
flush_vertex(split);
}
void
_tnl_split_inplace(struct gl_context *ctx,
const struct tnl_vertex_array *arrays,
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint num_instances,
GLuint base_instance,
tnl_draw_func draw,
const struct split_limits *limits)
{
struct split_context split;
memset(&split, 0, sizeof(split));
split.ctx = ctx;
split.array = arrays;
split.prim = prim;
split.nr_prims = nr_prims;
split.ib = ib;
/* Empty interval, makes calculations simpler. */
split.min_index = ~0;
split.max_index = 0;
split.num_instances = num_instances;
split.base_instance = base_instance;
split.draw = draw;
split.limits = limits;
split.limit = ib ? limits->max_indices : limits->max_verts;
split_prims(&split);
}

View File

@ -1,317 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
do { \
if (mask & PLANE_BIT) { \
GLuint idxPrev = inlist[0]; \
GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
GLuint outcount = 0; \
GLuint i; \
\
inlist[n] = inlist[0]; /* prevent rotation of vertices */ \
for (i = 1; i <= n; i++) { \
GLuint idx = inlist[i]; \
GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \
\
if (dpPrev >= 0.0f) { \
outlist[outcount++] = idxPrev; \
} \
\
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
if (dp < 0.0f) { \
/* Going out of bounds. Avoid division by zero as we \
* know dp != dpPrev from DIFFERENT_SIGNS, above. \
*/ \
GLfloat t = dp / (dp - dpPrev); \
INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \
interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \
} else { \
/* Coming back in. \
*/ \
GLfloat t = dpPrev / (dpPrev - dp); \
INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \
interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \
} \
outlist[outcount++] = newvert++; \
} \
\
idxPrev = idx; \
dpPrev = dp; \
} \
\
if (outcount < 3) \
return; \
\
{ \
GLuint *tmp = inlist; \
inlist = outlist; \
outlist = tmp; \
n = outcount; \
} \
} \
} while (0)
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
do { \
if (mask & PLANE_BIT) { \
const GLfloat dp0 = CLIP_DOTPROD( v0, A, B, C, D ); \
const GLfloat dp1 = CLIP_DOTPROD( v1, A, B, C, D ); \
const GLboolean neg_dp0 = dp0 < 0.0f; \
const GLboolean neg_dp1 = dp1 < 0.0f; \
\
/* For regular clipping, we know from the clipmask that one \
* (or both) of these must be negative (otherwise we wouldn't \
* be here). \
* For userclip, there is only a single bit for all active \
* planes, so we can end up here when there is nothing to do, \
* hence the second < 0.0f test: \
*/ \
if (neg_dp0 && neg_dp1) \
return; /* both vertices outside clip plane: discard */ \
\
if (neg_dp1) { \
GLfloat t = dp1 / (dp1 - dp0); \
if (t > t1) t1 = t; \
} else if (neg_dp0) { \
GLfloat t = dp0 / (dp0 - dp1); \
if (t > t0) t0 = t; \
} \
if (t0 + t1 >= 1.0) \
return; /* discard */ \
} \
} while (0)
/* Clip a line against the viewport and user clip planes.
*/
static inline void
TAG(clip_line)( struct gl_context *ctx, GLuint v0, GLuint v1, GLubyte mask )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
tnl_interp_func interp = tnl->Driver.Render.Interp;
GLfloat (*coord)[4] = VB->ClipPtr->data;
GLuint newvert = VB->Count;
GLfloat t0 = 0;
GLfloat t1 = 0;
const GLuint v0_orig = v0;
if (mask & CLIP_FRUSTUM_BITS) {
LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
LINE_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
LINE_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
LINE_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
}
if (mask & CLIP_USER_BIT) {
GLbitfield enabled = ctx->Transform.ClipPlanesEnabled;
while (enabled) {
const int p = u_bit_scan(&enabled);
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
LINE_CLIP( CLIP_USER_BIT, a, b, c, d );
}
}
if (VB->ClipMask[v0]) {
INTERP_4F( t0, coord[newvert], coord[v0], coord[v1] );
interp( ctx, t0, newvert, v0, v1, GL_FALSE );
v0 = newvert;
newvert++;
}
else {
assert(t0 == 0.0);
}
/* Note: we need to use vertex v0_orig when computing the new
* interpolated/clipped vertex position, not the current v0 which
* may have got set when we clipped the other end of the line!
*/
if (VB->ClipMask[v1]) {
INTERP_4F( t1, coord[newvert], coord[v1], coord[v0_orig] );
interp( ctx, t1, newvert, v1, v0_orig, GL_FALSE );
if (ctx->Light.ShadeModel == GL_FLAT)
tnl->Driver.Render.CopyPV( ctx, newvert, v1 );
v1 = newvert;
newvert++;
}
else {
assert(t1 == 0.0);
}
tnl->Driver.Render.ClippedLine( ctx, v0, v1 );
}
/* Clip a triangle against the viewport and user clip planes.
*/
static inline void
TAG(clip_tri)( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
tnl_interp_func interp = tnl->Driver.Render.Interp;
GLuint newvert = VB->Count;
GLfloat (*coord)[4] = VB->ClipPtr->data;
GLuint pv = v2;
GLuint vlist[2][MAX_CLIPPED_VERTICES];
GLuint *inlist = vlist[0], *outlist = vlist[1];
GLuint n = 3;
ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
if (0) {
/* print pre-clip vertex coords */
GLuint i, j;
printf("pre clip:\n");
for (i = 0; i < n; i++) {
j = inlist[i];
printf(" %u: %u: %f, %f, %f, %f\n",
i, j,
coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
assert(!util_is_inf_or_nan(coord[j][0]));
assert(!util_is_inf_or_nan(coord[j][1]));
assert(!util_is_inf_or_nan(coord[j][2]));
assert(!util_is_inf_or_nan(coord[j][3]));
}
}
if (mask & CLIP_FRUSTUM_BITS) {
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
}
if (mask & CLIP_USER_BIT) {
GLbitfield enabled = ctx->Transform.ClipPlanesEnabled;
while (enabled) {
const int p = u_bit_scan(&enabled);
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
}
}
if (ctx->Light.ShadeModel == GL_FLAT) {
if (pv != inlist[0]) {
assert( inlist[0] >= VB->Count );
tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
}
}
if (0) {
/* print post-clip vertex coords */
GLuint i, j;
printf("post clip:\n");
for (i = 0; i < n; i++) {
j = inlist[i];
printf(" %u: %u: %f, %f, %f, %f\n",
i, j,
coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
}
}
tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
}
/* Clip a quad against the viewport and user clip planes.
*/
static inline void
TAG(clip_quad)( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
GLubyte mask )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
tnl_interp_func interp = tnl->Driver.Render.Interp;
GLuint newvert = VB->Count;
GLfloat (*coord)[4] = VB->ClipPtr->data;
GLuint pv = v3;
GLuint vlist[2][MAX_CLIPPED_VERTICES];
GLuint *inlist = vlist[0], *outlist = vlist[1];
GLuint n = 4;
ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */
if (mask & CLIP_FRUSTUM_BITS) {
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
}
if (mask & CLIP_USER_BIT) {
GLbitfield enabled = ctx->Transform.ClipPlanesEnabled;
while (enabled) {
const int p = u_bit_scan(&enabled);
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
}
}
if (ctx->Light.ShadeModel == GL_FLAT) {
if (pv != inlist[0]) {
assert( inlist[0] >= VB->Count );
tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
}
}
tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
}
#undef W
#undef Z
#undef Y
#undef X
#undef SIZE
#undef TAG
#undef POLY_CLIP
#undef LINE_CLIP

View File

@ -1,277 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keithw@vmware.com>
*/
#include "c99_math.h"
#include "main/errors.h"
#include "main/glheader.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "math/m_xform.h"
#include "t_context.h"
#include "t_pipeline.h"
struct fog_stage_data {
GLvector4f fogcoord; /* has actual storage allocated */
};
#define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr)
#define FOG_EXP_TABLE_SIZE 256
#define FOG_MAX (10.0F)
#define EXP_FOG_MAX .0006595F
#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
static GLfloat inited = 0;
#if 1
#define NEG_EXP( result, narg ) \
do { \
GLfloat f = (GLfloat) (narg * (1.0F / FOG_INCR)); \
GLint k = (GLint) f; \
if (k > FOG_EXP_TABLE_SIZE-2) \
result = (GLfloat) EXP_FOG_MAX; \
else \
result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]); \
} while (0)
#else
#define NEG_EXP( result, narg ) \
do { \
result = exp(-narg); \
} while (0)
#endif
/**
* Initialize the exp_table[] lookup table for approximating exp().
*/
static void
init_static_data( void )
{
GLfloat f = 0.0F;
GLint i = 0;
for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
exp_table[i] = expf(-f);
}
inited = 1;
}
/**
* Compute per-vertex fog blend factors from fog coordinates by
* evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function.
* Fog coordinates are distances from the eye (typically between the
* near and far clip plane distances).
* Note that fogcoords may be negative, if eye z is source absolute
* value must be taken earlier.
* Fog blend factors are in the range [0,1].
*/
static void
compute_fog_blend_factors(struct gl_context *ctx, GLvector4f *out, const GLvector4f *in)
{
GLfloat end = ctx->Fog.End;
GLfloat *v = in->start;
GLuint stride = in->stride;
GLuint n = in->count;
GLfloat (*data)[4] = out->data;
GLfloat d;
GLuint i;
out->count = in->count;
switch (ctx->Fog.Mode) {
case GL_LINEAR:
if (ctx->Fog.Start == ctx->Fog.End)
d = 1.0F;
else
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
const GLfloat z = *v;
GLfloat f = (end - z) * d;
data[i][0] = CLAMP(f, 0.0F, 1.0F);
}
break;
case GL_EXP:
d = ctx->Fog.Density;
for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) {
const GLfloat z = *v;
NEG_EXP( data[i][0], d * z );
}
break;
case GL_EXP2:
d = ctx->Fog.Density*ctx->Fog.Density;
for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
const GLfloat z = *v;
NEG_EXP( data[i][0], d * z * z );
}
break;
default:
_mesa_problem(ctx, "Bad fog mode in make_fog_coord");
return;
}
}
static GLboolean
run_fog_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
struct fog_stage_data *store = FOG_STAGE_DATA(stage);
GLvector4f *input;
if (!ctx->Fog.Enabled)
return GL_TRUE;
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && !ctx->VertexProgram._Current) {
GLuint i;
GLfloat *coord;
/* Fog is computed from vertex or fragment Z values */
/* source = VB->AttribPtr[_TNL_ATTRIB_POS] or VB->EyePtr coords */
/* dest = VB->AttribPtr[_TNL_ATTRIB_FOG] = fog stage private storage */
VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord;
if (!ctx->_NeedEyeCoords) {
/* compute fog coords from object coords */
const GLfloat *m = ctx->ModelviewMatrixStack.Top->m;
GLfloat plane[4];
/* Use this to store calculated eye z values:
*/
input = &store->fogcoord;
plane[0] = m[2];
plane[1] = m[6];
plane[2] = m[10];
plane[3] = m[14];
/* Full eye coords weren't required, just calculate the
* eye Z values.
*/
_mesa_dotprod_tab[VB->AttribPtr[_TNL_ATTRIB_POS]->size]
( (GLfloat *) input->data,
4 * sizeof(GLfloat),
VB->AttribPtr[_TNL_ATTRIB_POS], plane );
input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;
/* make sure coords are really positive
NOTE should avoid going through array twice */
coord = input->start;
for (i = 0; i < input->count; i++) {
*coord = fabsf(*coord);
STRIDE_F(coord, input->stride);
}
}
else {
/* fog coordinates = eye Z coordinates - need to copy for ABS */
input = &store->fogcoord;
if (VB->EyePtr->size < 2)
_mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 );
input->stride = 4 * sizeof(GLfloat);
input->count = VB->EyePtr->count;
coord = VB->EyePtr->start;
for (i = 0 ; i < VB->EyePtr->count; i++) {
input->data[i][0] = fabsf(coord[2]);
STRIDE_F(coord, VB->EyePtr->stride);
}
}
}
else {
/* use glFogCoord() coordinates */
input = VB->AttribPtr[_TNL_ATTRIB_FOG]; /* source data */
/* input->count may be one if glFogCoord was only called once
* before glBegin. But we need to compute fog for all vertices.
*/
input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;
VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord; /* dest data */
}
if (tnl->_DoVertexFog) {
/* compute blend factors from fog coordinates */
compute_fog_blend_factors( ctx, VB->AttribPtr[_TNL_ATTRIB_FOG], input );
}
else {
/* results = incoming fog coords (compute fog per-fragment later) */
VB->AttribPtr[_TNL_ATTRIB_FOG] = input;
}
return GL_TRUE;
}
/* Called the first time stage->run() is invoked.
*/
static GLboolean
alloc_fog_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct fog_stage_data *store;
stage->privatePtr = malloc(sizeof(*store));
store = FOG_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
_mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 );
if (!inited)
init_static_data();
return GL_TRUE;
}
static void
free_fog_data(struct tnl_pipeline_stage *stage)
{
struct fog_stage_data *store = FOG_STAGE_DATA(stage);
if (store) {
_mesa_vector4f_free( &store->fogcoord );
free( store );
stage->privatePtr = NULL;
}
}
const struct tnl_pipeline_stage _tnl_fog_coordinate_stage =
{
"build fog coordinates", /* name */
NULL, /* private_data */
alloc_fog_data, /* dtr */
free_fog_data, /* dtr */
NULL, /* check */
run_fog_stage /* run -- initially set to init. */
};

Some files were not shown because too many files have changed in this diff Show More